2021-12-07 14:09:36 +00:00
|
|
|
:PROPERTIES:
|
|
|
|
:ID: 1208f09c-d37d-4e6b-9110-151f3c6b7d34
|
|
|
|
:END:
|
2021-12-07 14:11:45 +00:00
|
|
|
#+TITLE: Cisco FT SecureX Simplified Registration
|
2021-12-07 14:09:36 +00:00
|
|
|
#+Author: Yann Esposito
|
|
|
|
#+Date: [2021-12-07]
|
2022-01-17 18:15:27 +00:00
|
|
|
#+OPTIONS: prop:t
|
2021-12-07 14:09:36 +00:00
|
|
|
|
|
|
|
- tags :: [[id:299643a7-00e5-47fb-a987-3b9278e89da3][Auth]]
|
2022-02-08 14:08:08 +00:00
|
|
|
- ref :: https://github.com/advthreat/response/issues/821
|
|
|
|
- source :: https://github.com/advthreat/iroh/issues/6076
|
2021-12-07 14:11:45 +00:00
|
|
|
- dashboard :: https://github.com/advthreat/iroh/projects/32
|
|
|
|
|
2022-01-17 14:08:37 +00:00
|
|
|
* Table of Content :TOC_3:QUOTE:
|
|
|
|
#+BEGIN_QUOTE
|
2022-01-17 13:51:34 +00:00
|
|
|
- [[#functional-spec][Functional Spec]]
|
2022-01-17 15:09:35 +00:00
|
|
|
- [[#15-technical-plan][=15= Technical Plan]]
|
2022-01-17 15:16:05 +00:00
|
|
|
- [[#0-support-private-email-vs-public-emails][=0= Support private email vs public emails]]
|
2022-01-17 13:51:34 +00:00
|
|
|
- [[#canceled-support-allow-list-exceptions-for-some-cisco-user][CANCELED Support allow-list exceptions for some Cisco user.]]
|
2022-01-17 15:09:35 +00:00
|
|
|
- [[#1-support-search-admin-with-same-email-domain][=1= Support, search admin with same email domain]]
|
|
|
|
- [[#10-new-ui-sync][=10= New UI Sync]]
|
|
|
|
- [[#1-new-auth-apis][=1= New Auth APIs]]
|
|
|
|
- [[#1-new-api-jwt-middleware][=1= New API JWT middleware]]
|
2022-02-08 14:12:36 +00:00
|
|
|
- [[#5-new-iroh-auth-api-endpoints][=5= New IROH-Auth API endpoints]]
|
2022-01-17 15:09:35 +00:00
|
|
|
- [[#2-new-iroh-auth-api][=2= New IROH-Auth API]]
|
2022-01-17 18:16:39 +00:00
|
|
|
- [[#1-new-iroh-auth-login-process][=1= New IROH-Auth login process.]]
|
2022-01-17 15:09:35 +00:00
|
|
|
- [[#3-email-notification-of-org-request-accesses][=3= Email Notification of Org Request Accesses]]
|
2022-01-17 13:51:34 +00:00
|
|
|
- [[#notes][Notes]]
|
2022-01-17 15:09:35 +00:00
|
|
|
- [[#2-org-requests-crud-api-for-admins-of-the-orgs][=2= Org Requests CRUD API for Admins of the Orgs]]
|
2022-01-17 13:51:34 +00:00
|
|
|
- [[#list][List]]
|
|
|
|
- [[#read][Read]]
|
2022-01-17 14:41:30 +00:00
|
|
|
- [[#patch-the-org-access][Patch the Org Access]]
|
2022-01-17 14:08:37 +00:00
|
|
|
#+END_QUOTE
|
2022-01-17 13:50:12 +00:00
|
|
|
|
2021-12-16 14:15:16 +00:00
|
|
|
* Functional Spec
|
|
|
|
|
|
|
|
Response issues:
|
|
|
|
- https://github.com/advthreat/response/issues/821
|
|
|
|
|
|
|
|
Figma: https://www.figma.com/file/Bz3m25kpWXpdct7AnhmNsW/SXSO-Registeration?node-id=759%3A5926
|
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
* =15= Technical Plan
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 15 rcd/
|
|
|
|
|
|
|
|
- rcd :: rcd stands for release cycle for 1 dev
|
2022-01-17 16:01:28 +00:00
|
|
|
|
2022-01-17 15:16:05 +00:00
|
|
|
** DONE =0= Support private email vs public emails
|
2021-12-07 14:14:39 +00:00
|
|
|
|
2022-01-17 10:42:11 +00:00
|
|
|
*DONE*
|
2022-01-17 16:03:23 +00:00
|
|
|
+/Estimate: 1 rcd after the list is provided./+
|
2021-12-15 15:23:58 +00:00
|
|
|
|
2021-12-07 14:14:39 +00:00
|
|
|
The solution is to use a blacklist of domains where any user could create
|
|
|
|
multiple email accounts pseudo-anonymously.
|
|
|
|
|
2021-12-16 14:16:36 +00:00
|
|
|
Details: https://github.com/advthreat/response/issues/979
|
|
|
|
|
2022-01-17 09:59:21 +00:00
|
|
|
*** CANCELED Support allow-list exceptions for some Cisco user.
|
|
|
|
:LOGBOOK:
|
|
|
|
- State "CANCELED" from "HOLD" [2022-01-17 Mon 10:57] \\
|
|
|
|
This only concern new account creation. User with gmail account could still login.
|
|
|
|
:END:
|
2021-12-16 14:18:02 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd after the list is provided./
|
2021-12-16 14:21:13 +00:00
|
|
|
|
2021-12-16 14:18:02 +00:00
|
|
|
Typically we should allow some users with an email like =some-user+XXX@gmail.com=
|
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
** =1= Support, search admin with same email domain
|
2021-12-07 14:16:58 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd./
|
2021-12-15 15:25:14 +00:00
|
|
|
Note: *Work in progress*
|
2021-12-15 15:23:58 +00:00
|
|
|
|
2021-12-07 14:16:58 +00:00
|
|
|
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.
|
2021-12-07 14:20:00 +00:00
|
|
|
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.
|
2021-12-07 14:16:58 +00:00
|
|
|
|
2021-12-07 14:21:58 +00:00
|
|
|
2. Search via text match.
|
|
|
|
|
|
|
|
|
|
|
|
The algorithm should look a bit like:
|
|
|
|
|
|
|
|
#+begin_src clojure
|
2021-12-07 14:24:11 +00:00
|
|
|
|
|
|
|
;; only when this is an unknown user
|
2021-12-07 14:59:57 +00:00
|
|
|
;; so a single approval will prevent the user to see this page.
|
2021-12-07 14:21:58 +00:00
|
|
|
(let [user-email ,,,
|
2021-12-07 14:24:11 +00:00
|
|
|
domain (string/replace user-email #".*@" "")
|
2021-12-07 14:25:27 +00:00
|
|
|
users (matching-admins domain) ;; returns a potentially big list of admin users
|
|
|
|
indexed-orgs (group-by :org-id users)]
|
|
|
|
(vals indexed-orgs))
|
2021-12-07 14:21:58 +00:00
|
|
|
#+end_src
|
|
|
|
|
2021-12-07 14:58:36 +00:00
|
|
|
|
|
|
|
Once this list of orgs is found.
|
2021-12-07 14:59:57 +00:00
|
|
|
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.
|
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
** =10= New UI Sync
|
2022-01-17 10:31:19 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 11 rcd/
|
2022-01-17 10:32:23 +00:00
|
|
|
|
2022-01-17 10:31:19 +00:00
|
|
|
We should find a way to hand the UI work to the UI team.
|
|
|
|
Right now, the page are all generated in IROH.
|
|
|
|
|
|
|
|
To reach that ideally we should sync the source code as a jar in IROH.
|
|
|
|
|
2022-01-17 10:44:55 +00:00
|
|
|
In order to give the UI the ability to make a front-end application, we
|
2022-01-17 10:39:18 +00:00
|
|
|
should create news APIS that support a new UserIdentity-level JWT
|
2022-01-17 10:33:46 +00:00
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
*** =1= New Auth APIs
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd/
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-02-01 11:05:31 +00:00
|
|
|
ref :: https://github.com/advthreat/iroh/issues/6242
|
|
|
|
|
2022-01-17 10:48:28 +00:00
|
|
|
Continue to use the =/code= route of iroh-auth.
|
2022-01-17 10:51:39 +00:00
|
|
|
But instead of returning a Session Token, it will return a UserIdentity Token.
|
2022-01-17 10:50:04 +00:00
|
|
|
This is a JWT with the important data from the IdP:
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-01-17 10:50:04 +00:00
|
|
|
- idp-id
|
|
|
|
- user-identity-id
|
|
|
|
- user-email
|
|
|
|
- etc…
|
|
|
|
|
2022-01-17 10:51:39 +00:00
|
|
|
When the user is redirected to an HTML generated page, we should add the
|
|
|
|
=code= in the anchor parameter of the route so the UI will be able to use
|
|
|
|
that code to retrieve a UserIdentity Token.
|
2022-01-17 14:51:40 +00:00
|
|
|
We should derive the current mechanism with code, but use the login code store.
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-01-21 13:40:59 +00:00
|
|
|
|
|
|
|
**** Tasks
|
|
|
|
|
|
|
|
- Create a new function to generate these new JWT using the "token-infos"
|
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
*** =1= New API JWT middleware
|
2022-01-17 10:52:43 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd/
|
2022-01-17 10:52:43 +00:00
|
|
|
|
2022-02-08 14:12:36 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6266
|
|
|
|
|
2022-01-17 10:52:43 +00:00
|
|
|
We need to change the configuration of the check JWT middleware to support
|
|
|
|
UserIdentity Token instead. And use this configuration for this new API.
|
|
|
|
|
2022-01-17 11:01:42 +00:00
|
|
|
The =user-identity-jwt= should contain enough data to retrieve:
|
|
|
|
- =idp-mapping=
|
|
|
|
- =user-email=
|
|
|
|
- all other metas, as user-name, user-nick, etc…
|
2022-01-21 13:40:59 +00:00
|
|
|
|
2022-02-08 14:12:36 +00:00
|
|
|
*** =5= New IROH-Auth API endpoints
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 5 rcd/
|
2022-02-08 14:12:36 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6268
|
|
|
|
|
2022-02-08 13:41:07 +00:00
|
|
|
**** =4= ~OrgAccessRequestService~
|
2022-01-17 15:03:13 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 4 rcd/
|
2022-01-17 14:47:18 +00:00
|
|
|
|
2022-02-08 14:11:03 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6272
|
|
|
|
|
2022-02-08 13:47:01 +00:00
|
|
|
This new service should be mostly a CRUD service on top of =TKStore= with the
|
2022-01-17 14:12:33 +00:00
|
|
|
following schema:
|
2022-01-17 14:01:08 +00:00
|
|
|
|
|
|
|
#+begin_src clojure
|
2022-01-17 14:29:54 +00:00
|
|
|
(s/defschema OrgAccessRequestStatus
|
|
|
|
(s/enum :pending :accepted :rejected))
|
|
|
|
|
2022-01-17 14:01:08 +00:00
|
|
|
(s/defschema OrgAccessRequest
|
|
|
|
(st/merge
|
|
|
|
{:id UUID
|
|
|
|
:idp-mapping IdPMapping
|
|
|
|
:user-email s/Str
|
|
|
|
:org-id s/Str
|
2022-01-17 14:29:54 +00:00
|
|
|
:status OrgAccessRequestStatus
|
2022-01-17 14:01:08 +00:00
|
|
|
:created-at DateTime}
|
|
|
|
(st/optional-keys
|
|
|
|
{:user-name s/Str
|
|
|
|
:user-nick s/Str
|
2022-01-21 14:05:10 +00:00
|
|
|
:granted-role Role ;; the role granted if the request is accepted
|
2022-01-17 14:01:08 +00:00
|
|
|
:approver-id UserId
|
|
|
|
:approver-email UserEmail ;; email of the approver
|
|
|
|
:updated-at DateTime
|
|
|
|
})))
|
|
|
|
#+end_src
|
|
|
|
|
2022-01-17 14:12:33 +00:00
|
|
|
#+begin_src clojure
|
|
|
|
(defprotocol OrgAccessRequestService
|
2022-01-17 14:14:43 +00:00
|
|
|
"See iroh-auth.registration.org-access-request.schemas/ServiceFns for schemas."
|
2022-01-17 14:13:41 +00:00
|
|
|
:extend-via-metadata true
|
|
|
|
|
2022-01-21 13:48:08 +00:00
|
|
|
;; service function for the Admins logged in SecureX
|
2022-01-17 14:24:08 +00:00
|
|
|
;; User filtered CRUD+Search for REST API related methods
|
2022-01-17 14:25:15 +00:00
|
|
|
(search-org-access-requests-for-org
|
|
|
|
[this request-identity filter-map pagination-params]
|
2022-01-17 14:26:17 +00:00
|
|
|
"Search all OrgAccessRequest of the org of the user of the request-identity")
|
2022-01-17 14:24:08 +00:00
|
|
|
|
2022-01-17 14:13:41 +00:00
|
|
|
(get-org-access-request
|
2022-01-17 14:16:06 +00:00
|
|
|
[this request-identity org-access-request-id]
|
2022-01-17 14:34:40 +00:00
|
|
|
"Return the OrgAccessRequest for a user using the org-access-request-id")
|
2022-01-17 14:13:41 +00:00
|
|
|
|
|
|
|
(patch-org-access-request
|
2022-01-17 14:16:06 +00:00
|
|
|
[this request-identity org-access-request-id org-access-request-patch]
|
2022-01-17 14:47:18 +00:00
|
|
|
"Change the status of an OrgAccessRequest to grant/reject it.
|
|
|
|
Note user creation could be a side effect.")
|
2022-01-17 14:13:41 +00:00
|
|
|
|
2022-01-21 13:49:57 +00:00
|
|
|
;; For the New Registration Page (the user logged in via the IdP successfully)
|
2022-01-17 14:56:56 +00:00
|
|
|
(search-org-access-requests-for-user-identity
|
|
|
|
[this user-identity filter-map pagination-params]
|
|
|
|
"Search all OrgAccessRequest made by this user identity accross all orgs.
|
|
|
|
This should only be visible via the registration page on the new API accepting
|
|
|
|
user-identity JWT")
|
|
|
|
|
2022-01-21 13:53:16 +00:00
|
|
|
(create-org-access-request
|
|
|
|
[this user-identity org-id]
|
2022-01-21 13:54:38 +00:00
|
|
|
"Create a new OrgAccessRequest.")
|
2022-01-21 13:53:16 +00:00
|
|
|
|
|
|
|
(delete-org-access-request
|
|
|
|
[this user-identity org-access-request-id]
|
2022-01-21 13:54:38 +00:00
|
|
|
"Remove an org request access.")
|
2022-01-21 13:53:16 +00:00
|
|
|
|
|
|
|
;; Internal CRUD+Search
|
2022-01-17 14:13:41 +00:00
|
|
|
(raw-search-org-access-requests
|
|
|
|
[this filter-map pagination-params]
|
2022-01-17 14:34:40 +00:00
|
|
|
"Search all OrgAccessRequest grants")
|
2022-01-17 14:13:41 +00:00
|
|
|
|
|
|
|
(raw-get-org-access-request
|
|
|
|
[this org-access-request-id]
|
2022-01-17 14:34:40 +00:00
|
|
|
"Return the OrgAccessRequest grant")
|
2022-01-17 14:13:41 +00:00
|
|
|
|
|
|
|
(raw-patch-org-access-request
|
|
|
|
[this org-access-request-id org-access-request-patch]
|
2022-01-17 14:39:25 +00:00
|
|
|
"Update the status of an OrgAccessRequest."))
|
2022-01-17 14:12:33 +00:00
|
|
|
#+end_src
|
2022-01-17 15:09:35 +00:00
|
|
|
***** =1= search/get/patch
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd/
|
2022-01-17 15:09:35 +00:00
|
|
|
***** =3= PATCH
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 3 rcd/
|
2022-01-17 14:58:23 +00:00
|
|
|
|
2022-01-17 15:02:07 +00:00
|
|
|
The org-access-request-patch should have the following schema:
|
2022-01-17 14:58:23 +00:00
|
|
|
|
2022-01-17 15:00:04 +00:00
|
|
|
#+begin_src clojure
|
|
|
|
{(s/optional-key :role) Role
|
|
|
|
:status (s/enum :accepted :rejected)}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
If the role is not provided, the default value should be =user=.
|
2022-02-08 13:47:01 +00:00
|
|
|
If the old ~OrgAccessRequest~ is not ~:pending~ this should throw a 400.
|
2022-01-17 15:02:07 +00:00
|
|
|
If the status is set to =:accepted=:
|
|
|
|
|
2022-02-08 13:47:01 +00:00
|
|
|
1. create a new user for the org of the ~OrgAccessRequest~.
|
2022-01-17 15:02:07 +00:00
|
|
|
2. send an email to the user that requested the access
|
|
|
|
|
2022-02-08 13:47:01 +00:00
|
|
|
If the status is set to =:rejected=, then send an email to the user that
|
2022-01-17 15:02:07 +00:00
|
|
|
requested the access.
|
|
|
|
|
|
|
|
Note we should test that the user created that way could login correctly.
|
2022-01-17 14:12:33 +00:00
|
|
|
|
2022-02-08 13:41:07 +00:00
|
|
|
**** =1= ~UserIdentityService~
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd/
|
2022-01-17 14:48:55 +00:00
|
|
|
|
2022-02-08 14:11:03 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6274
|
|
|
|
|
2022-02-08 13:45:37 +00:00
|
|
|
Create a new service dedicated to ~UserIdentities~.
|
2022-02-08 13:42:27 +00:00
|
|
|
|
|
|
|
#+begin_src clojure
|
|
|
|
(defprotocol UserIdentityService
|
2022-02-08 13:44:23 +00:00
|
|
|
"Service which handle UserIdentities (mostly CRUD operations). "
|
|
|
|
(create-user-identity [this user-params])
|
|
|
|
(get-user-identity [this user-id])
|
|
|
|
(update-user-identity [this user-params])
|
2022-02-08 13:42:27 +00:00
|
|
|
(update-login-date [this user-id])
|
2022-02-08 13:44:23 +00:00
|
|
|
(search-user-identities
|
2022-02-08 13:42:27 +00:00
|
|
|
[this filter-map pagination-params]
|
|
|
|
[this filter-map pagination-params stringmatch-query-params])
|
2022-02-08 13:44:23 +00:00
|
|
|
(delete-user-identity [this user-id]))
|
2022-02-08 13:42:27 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-01-17 14:02:37 +00:00
|
|
|
It should also contain a field containing a set of hidden org-ids that will
|
|
|
|
be the orgs not to display on the registration webpages.
|
|
|
|
|
2022-01-17 14:04:00 +00:00
|
|
|
#+begin_src clojure
|
|
|
|
(s/defschema UserIdentity
|
|
|
|
(ist/open-schema-any-keys
|
2022-01-17 14:05:09 +00:00
|
|
|
{:id s/Str
|
|
|
|
:email
|
|
|
|
:name
|
|
|
|
:nickname
|
|
|
|
:last-logged-in [,,,]
|
2022-02-08 13:45:37 +00:00
|
|
|
(s/optional-key :hidden-orgs) #{,,,}}))
|
2022-01-17 14:02:37 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
*** =2= New IROH-Auth API
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-02-08 13:55:47 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6268
|
|
|
|
|
2022-02-09 10:43:29 +00:00
|
|
|
/Estimate: 4 rcd/
|
2022-01-17 14:48:55 +00:00
|
|
|
/Depends: IROH-Auth CRUD Service/
|
2022-01-17 11:15:11 +00:00
|
|
|
|
2022-01-17 10:55:32 +00:00
|
|
|
This new API should only work with UserIdentity JWT.
|
2022-01-17 10:46:39 +00:00
|
|
|
|
2022-01-17 10:55:32 +00:00
|
|
|
#+begin_src
|
2022-02-08 12:57:55 +00:00
|
|
|
GET /iroh/iroh-auth-ui/whoami ;; whoami at the User Identity level
|
|
|
|
POST /iroh/iroh-auth-ui/org-access/:org-id ;; request access to a matching org
|
|
|
|
POST /iroh/iroh-auth-ui/hide-org/:org-id ;; ability to hide an org-access
|
|
|
|
GET /iroh/iroh-auth-ui/matching-accounts ;; list all the matching accounts
|
|
|
|
GET /iroh/iroh-auth-ui/matching-orgs ;; list all the matching orgs
|
|
|
|
GET /iroh/iroh-auth-ui/pending-invites ;; list all the pending invites
|
|
|
|
GET /iroh/iroh-auth-ui/registration-view ;; helper to make a single http call
|
2022-01-17 10:54:23 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-02-08 13:58:19 +00:00
|
|
|
**** =whoami= Endpoint
|
2022-02-08 14:08:08 +00:00
|
|
|
|
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6266
|
|
|
|
|
2022-02-08 13:58:19 +00:00
|
|
|
Write an endpoint that would use the ~UserIdentity~ JWT and decode it.
|
|
|
|
Ideally should instead read the value in DB via the ~UserIdentityService~.
|
2022-02-09 10:18:26 +00:00
|
|
|
**** Create New Account
|
|
|
|
|
2022-02-09 10:43:29 +00:00
|
|
|
/Estimate: 2 rcd/
|
2022-02-09 10:40:57 +00:00
|
|
|
|
2022-02-09 10:37:38 +00:00
|
|
|
Create a new endpoint to create a new account (user + org):
|
|
|
|
|
2022-02-09 10:30:12 +00:00
|
|
|
#+begin_src http
|
|
|
|
GET /iroh/iroh-auth-ui/create-new-account
|
|
|
|
|
|
|
|
Accept: application/json
|
|
|
|
Content-Type: application/json
|
|
|
|
User-Agent: ob-http
|
|
|
|
Authorization: Bearer ${user-identity-jwt}
|
2022-02-09 10:33:35 +00:00
|
|
|
|
2022-02-09 10:36:23 +00:00
|
|
|
{"org-name":"Cisco",
|
|
|
|
"country":"US"}
|
2022-02-09 10:30:12 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-02-09 10:33:35 +00:00
|
|
|
#+begin_src clojure
|
|
|
|
(s/defschema NewAccount
|
|
|
|
(st/merge
|
2022-02-09 10:35:16 +00:00
|
|
|
{:org-name :- s/Str
|
|
|
|
:country :- (apply s/enum country-iso-codes)
|
2022-02-09 10:33:35 +00:00
|
|
|
(st/optional-keys
|
|
|
|
{:department :- s/Str
|
|
|
|
:street1 :- s/Str
|
|
|
|
:street2 :- s/Str
|
|
|
|
:postal-code :- s/Str
|
|
|
|
:city :- s/Str})}))
|
|
|
|
|
2022-02-09 10:36:23 +00:00
|
|
|
(POST "/create-new-account" []
|
2022-02-09 10:33:35 +00:00
|
|
|
:summary "Given a code and some org-settings create a new account (new org and new user)"
|
|
|
|
:description "This is an internal temporary route needed to select the user/org."
|
2022-02-09 10:35:16 +00:00
|
|
|
:body [{:keys [country
|
|
|
|
org-name
|
|
|
|
department
|
|
|
|
street1
|
|
|
|
street2
|
|
|
|
postal-code
|
|
|
|
city] :as new-account} NewAccount]
|
2022-02-09 10:33:35 +00:00
|
|
|
(let [address (iroh-core/assoc-some?
|
|
|
|
{:country-iso-code country}
|
|
|
|
:department department
|
|
|
|
:street1 street1
|
|
|
|
:street2 street2
|
|
|
|
:postal-code postal-code
|
|
|
|
:city city)
|
|
|
|
org-settings {:name org-name
|
|
|
|
:address address}]
|
2022-02-09 10:36:23 +00:00
|
|
|
(create-new-account org-settings)))
|
2022-02-09 10:33:35 +00:00
|
|
|
#+end_src
|
2022-02-09 10:30:12 +00:00
|
|
|
|
2022-02-09 10:37:38 +00:00
|
|
|
As we now have a session, we should take care about a few details:
|
|
|
|
|
|
|
|
- should we keep track of the =origin=?
|
2022-02-09 10:42:15 +00:00
|
|
|
YES this is a security risk to prevent an attack with a redirect to the
|
|
|
|
wrong endpoint. So the redirect should be handled by the backend.
|
2022-02-09 10:39:02 +00:00
|
|
|
- should we prevent a user identity to create multiple accounts?
|
2022-02-09 10:42:15 +00:00
|
|
|
I don't think so. Not in the first round at least.
|
2022-02-09 10:43:29 +00:00
|
|
|
It will probably be easy to add a =created-by= metas in the org, and prevent
|
|
|
|
duplicates (or put a maximal number of authorized enabled orgs)
|
2022-02-09 10:37:38 +00:00
|
|
|
|
2022-02-09 10:43:29 +00:00
|
|
|
**** List Matching Accounts - ref ::
|
|
|
|
https://github.com/advthreat/iroh/issues/6270 #+begin_src http GET
|
|
|
|
/iroh/iroh-auth-ui/matching-accounts
|
2022-02-08 13:59:26 +00:00
|
|
|
|
|
|
|
Accept: application/json
|
|
|
|
Content-Type: application/json
|
|
|
|
User-Agent: ob-http
|
|
|
|
Authorization: Bearer ${user-identity-jwt}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
It should return a list of object with the following schema sorted by last
|
|
|
|
logged in time by the user:
|
|
|
|
|
|
|
|
#+begin_src clojure
|
|
|
|
{:user User
|
|
|
|
:org Org
|
|
|
|
:last-login-date DateTime
|
|
|
|
:relative-last-login s/Str
|
|
|
|
:org-created-at DateTime
|
|
|
|
:relative-org-created-at s/Str
|
|
|
|
:activated? s/Bool
|
|
|
|
:org-nb-users s/Int}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
Mainly should return the data structure used in the current selection
|
|
|
|
account page using similar order and functionalities.
|
|
|
|
**** List Pending Invites
|
|
|
|
|
2022-02-08 14:09:51 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6269
|
|
|
|
|
2022-02-08 13:59:26 +00:00
|
|
|
#+begin_src http
|
|
|
|
GET /iroh/iroh-auth-ui/pending-invites
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
Here is an example value:
|
|
|
|
|
|
|
|
#+begin_src clojure
|
|
|
|
[{:role "admin",
|
|
|
|
:org-id "org-1",
|
|
|
|
:expires-in-nb-days 7,
|
|
|
|
:status "pending",
|
|
|
|
:invitee-email "chuck@example.org",
|
|
|
|
:inviter-user-id "org-1-admin-1"}]
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
We already retrieve pending invite in the code. The work would be about
|
|
|
|
taking care of having a specialized method from either an existing or a new
|
|
|
|
TK service dedicated to this functionality.
|
|
|
|
|
|
|
|
Use this method to expose it via the API.
|
2022-01-17 10:54:23 +00:00
|
|
|
**** Request Org Access
|
2022-01-17 10:33:46 +00:00
|
|
|
|
2022-02-08 14:09:51 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6273
|
|
|
|
|
2022-01-17 13:54:08 +00:00
|
|
|
We need to create another store with 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
|
|
|
|
:approver-id UserId
|
|
|
|
:approver-email UserEmail ;; email of the approver
|
|
|
|
:updated-at DateTime
|
|
|
|
})))
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
When a user request access to an organization.
|
|
|
|
We should create this object in DB.
|
|
|
|
|
|
|
|
|
2022-01-17 11:00:21 +00:00
|
|
|
#+begin_src
|
2022-02-08 13:05:01 +00:00
|
|
|
POST /iroh/iroh-auth-ui/org-access/:org-id ;; request access to a matching org
|
2022-01-17 11:00:21 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-01-17 10:33:46 +00:00
|
|
|
#+begin_src http
|
2022-02-08 13:05:01 +00:00
|
|
|
POST /iroh/iroh-auth-ui/org-access/:org-id
|
2022-01-17 10:33:46 +00:00
|
|
|
|
|
|
|
Accept: application/json
|
|
|
|
Content-Type: application/json
|
|
|
|
User-Agent: ob-http
|
|
|
|
Authorization: Bearer ${user-identity-jwt}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
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.
|
2022-01-17 15:06:14 +00:00
|
|
|
2. Send emails (see the [[*[3] Email Notification of Org Request Accesses]] section)
|
2022-01-17 11:17:03 +00:00
|
|
|
|
2022-01-17 13:35:54 +00:00
|
|
|
**** List Matching Orgs
|
2022-01-17 14:29:54 +00:00
|
|
|
|
2022-02-08 14:09:51 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6271
|
|
|
|
|
2022-01-17 13:38:28 +00:00
|
|
|
#+begin_src http
|
2022-02-08 13:05:01 +00:00
|
|
|
GET /iroh/iroh-auth-ui/matching-orgs
|
2022-01-17 13:38:28 +00:00
|
|
|
#+end_src
|
2022-01-17 13:44:35 +00:00
|
|
|
|
2022-02-08 13:17:53 +00:00
|
|
|
Given a ~UserIdentity~ with some email.
|
|
|
|
Should return every Org whose at least one admin has an email with the same
|
|
|
|
domain address.
|
2022-02-08 13:19:06 +00:00
|
|
|
So if you login via ~chuck@cisco.com~ you should return all orgs for which
|
|
|
|
there is at least one admin with a ~cisco.com~ email address.
|
2022-02-08 13:17:53 +00:00
|
|
|
|
2022-01-17 13:44:35 +00:00
|
|
|
Should return a list of objects with the following schema (sort to be defined):
|
|
|
|
|
|
|
|
#+begin_src clojure
|
2022-01-17 13:46:33 +00:00
|
|
|
{:org Org
|
2022-01-17 14:28:35 +00:00
|
|
|
:org-nb-users s/Int
|
|
|
|
:org-request-access-status OrgRequestAccessStatus}
|
2022-01-17 13:44:35 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-02-08 13:20:41 +00:00
|
|
|
*Note*
|
|
|
|
|
|
|
|
This endpoint is not straightforward.
|
2022-02-08 13:21:48 +00:00
|
|
|
We should list all current matching org, and concurrently list all current
|
2022-01-17 14:28:35 +00:00
|
|
|
=OrgRequestAccess= made by this =UserIdentity=.
|
2022-02-08 13:21:48 +00:00
|
|
|
Optionally we might also retrieve the orgs marked as hidden for this =UserIdentity= in DB.
|
2022-01-17 14:26:17 +00:00
|
|
|
|
2022-02-08 13:21:48 +00:00
|
|
|
We shall finally return a list of orgs with the current status and remove
|
|
|
|
the hidden ones.
|
2022-02-08 13:23:00 +00:00
|
|
|
|
|
|
|
We could probably imagine we want to support a query parameter to show
|
2022-02-08 13:24:07 +00:00
|
|
|
the hidden orgs in case a user want to cancel the hiding of some org.
|
2022-01-17 13:37:07 +00:00
|
|
|
**** Registration View
|
2022-02-08 14:09:51 +00:00
|
|
|
|
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6275
|
|
|
|
|
|
|
|
#+begin_src http
|
2022-02-08 13:05:01 +00:00
|
|
|
GET /iroh/iroh-auth-ui/registration-view
|
2022-02-08 14:09:51 +00:00
|
|
|
#+end_src
|
2022-01-17 13:37:07 +00:00
|
|
|
|
|
|
|
Should return the same result as the union of the calls to
|
|
|
|
=matching-accounts=, =matching-orgs= and =pending-invites=.
|
2022-01-17 11:17:03 +00:00
|
|
|
|
2022-01-17 13:38:28 +00:00
|
|
|
#+begin_src clojure
|
|
|
|
{:matching-accounts [,,,]
|
|
|
|
:matching-orgs [,,,]
|
|
|
|
:pending-invites [,,,]}
|
|
|
|
#+end_src
|
2022-02-08 14:05:51 +00:00
|
|
|
**** Hide Matching Org
|
2022-02-08 13:57:15 +00:00
|
|
|
|
2022-02-08 14:11:03 +00:00
|
|
|
- ref :: https://github.com/advthreat/iroh/issues/6276
|
|
|
|
|
2022-02-08 13:57:15 +00:00
|
|
|
#+begin_src http
|
|
|
|
POST /iroh/iroh-auth-ui/hide-org/:org-id
|
|
|
|
|
|
|
|
Accept: application/json
|
|
|
|
Content-Type: application/json
|
|
|
|
User-Agent: ob-http
|
|
|
|
Authorization: Bearer ${user-identity-jwt}
|
|
|
|
#+end_src
|
|
|
|
|
2022-02-08 14:05:51 +00:00
|
|
|
Should save in the ~UserIdentity~ store a new ~org-id~ to hide.
|
|
|
|
This impacts the call to ~matching-orgs~ such that orgs marked as hidden
|
|
|
|
should not be displayed when calling the ~matching-org~ route.
|
2022-02-08 13:57:15 +00:00
|
|
|
|
2022-01-17 18:16:39 +00:00
|
|
|
*** =1= New IROH-Auth login process.
|
2022-01-17 13:38:28 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 1 rcd/
|
2022-01-17 14:50:07 +00:00
|
|
|
|
2022-01-17 14:10:08 +00:00
|
|
|
Every-time a users successfully login via an IdP we should synchronize the
|
|
|
|
=UserIdentity= value in our DB accordingly.
|
|
|
|
It should occurs not only during the account registration, but also for
|
|
|
|
every new login.
|
2022-01-17 10:33:46 +00:00
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
** =3= Email Notification of Org Request Accesses
|
2021-12-07 15:16:47 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 3 rcd after email+html templates/
|
2021-12-15 15:26:24 +00:00
|
|
|
|
2021-12-07 15:18:13 +00:00
|
|
|
1. List all the admins of the requested org.
|
2021-12-07 15:19:17 +00:00
|
|
|
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.
|
2021-12-07 15:16:47 +00:00
|
|
|
|
2021-12-07 15:21:46 +00:00
|
|
|
*TODO* Have an email template (both HTML and Text)
|
2021-12-15 15:28:15 +00:00
|
|
|
*** Notes
|
|
|
|
|
|
|
|
Need to be able to trigger a new request to join after 7 days.
|
2021-12-07 15:21:46 +00:00
|
|
|
|
2022-01-17 15:09:35 +00:00
|
|
|
** =2= Org Requests CRUD API for Admins of the Orgs
|
2021-12-07 14:30:29 +00:00
|
|
|
|
2022-01-17 16:03:23 +00:00
|
|
|
/Estimate: 2 rcd after mail templates + text/
|
2021-12-16 14:48:40 +00:00
|
|
|
|
2021-12-07 14:38:46 +00:00
|
|
|
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
|
2022-01-21 14:03:10 +00:00
|
|
|
- ~PATCH /iroh/user-mgmt/org-requests/<id>~ Grant or Reject the access
|
2021-12-07 14:30:29 +00:00
|
|
|
|
2021-12-07 14:42:50 +00:00
|
|
|
*** List
|
|
|
|
|
2021-12-07 14:44:24 +00:00
|
|
|
~GET /iroh/user-mgmt/org-requests~
|
|
|
|
|
2021-12-07 14:56:39 +00:00
|
|
|
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):
|
2021-12-07 14:45:38 +00:00
|
|
|
|
|
|
|
- =pending=
|
|
|
|
- =accepted=
|
|
|
|
- =rejected=
|
2021-12-07 14:44:24 +00:00
|
|
|
|
2021-12-07 14:47:09 +00:00
|
|
|
Note we should probably support duplicate statuses.
|
|
|
|
Ex:
|
|
|
|
|
2021-12-07 14:48:14 +00:00
|
|
|
~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.
|
2021-12-07 14:47:09 +00:00
|
|
|
|
2022-01-17 14:41:30 +00:00
|
|
|
*** Patch the Org Access
|
2021-12-07 14:52:03 +00:00
|
|
|
|
2022-01-17 14:41:30 +00:00
|
|
|
~PATCH /iroh/user-mgmt/org-requests/<id>~ Grant/Reject the access
|
2021-12-07 14:52:03 +00:00
|
|
|
|
2022-01-17 14:45:06 +00:00
|
|
|
The body should be a JSON Object with:
|
2022-01-17 14:46:15 +00:00
|
|
|
- an optional field =role= whose value could be either =admin= or =user= (default
|
|
|
|
to =user=)
|
2022-01-17 14:45:06 +00:00
|
|
|
- a mandatory =status= field whose value could be either =accepted= or =rejected=.
|
2022-01-17 14:43:50 +00:00
|
|
|
|
2022-01-17 14:45:06 +00:00
|
|
|
A few examples of valid values:
|
2021-12-07 14:53:58 +00:00
|
|
|
|
|
|
|
#+begin_src js
|
2022-01-21 14:05:10 +00:00
|
|
|
{"granted-role":"admin"
|
2022-01-17 14:45:06 +00:00
|
|
|
"status":"accepted"}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src js
|
|
|
|
{"status":"accepted"}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src js
|
|
|
|
{"status":"rejected"}
|
2021-12-07 14:53:58 +00:00
|
|
|
#+end_src
|
|
|
|
|
2022-01-17 14:46:15 +00:00
|
|
|
During the call we should:
|
2021-12-07 14:52:03 +00:00
|
|
|
|
|
|
|
1. Create a new user with:
|
|
|
|
|
|
|
|
#+begin_src clojure
|
|
|
|
{:user-id (gen-uuid)
|
2021-12-07 14:56:39 +00:00
|
|
|
:org-id (:org-id org-access-request)
|
2021-12-07 14:52:03 +00:00
|
|
|
: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)
|
2021-12-07 14:53:58 +00:00
|
|
|
:role (get-in request [:body :role])
|
|
|
|
:enabled? true
|
2021-12-07 14:52:03 +00:00
|
|
|
}
|
|
|
|
#+end_src
|
|
|
|
|
2021-12-07 15:20:31 +00:00
|
|
|
2. Send an email to user confirming his access was granted.
|
|
|
|
|
2021-12-07 15:35:21 +00:00
|
|
|
*TODO* have an email template + text.
|
2021-12-07 15:21:46 +00:00
|
|
|
|