deft/Cisco.org.gpg_archive
Yann Esposito (Yogsototh) b8297d8f91
Updated cisco notes
2019-01-17 13:38:51 +01:00

1135 lines
37 KiB
Org Mode

# -*- mode: org -*-
Archived entries from file /Users/yaesposi/.deft/Cisco.org.gpg
* [#A] OAuth2 Provider
:PROPERTIES:
:ARCHIVE_TIME: 2019-01-09 Wed 10:52
:ARCHIVE_FILE: ~/.deft/Cisco.org.gpg
:ARCHIVE_OLPATH: Epics
:ARCHIVE_CATEGORY: Cisco.org
:END:
:SCHEDULE: <2018-01-11 Thu>
:END:
** Workflow
Authorize, Approve, Refuse, Token
Threatgrid portal would like access to the (enrich API, response API, ...
Private CTIA Public CTIA) -> scopes
users ses yes, he approves, POST approve, get back auth code, POST that to token
*** =/authorize=
Ask the user to authorize an App to access sub services API:
Grants: https://alexbilbie.com/guide-to-oauth-2-grants/
We'll never support grant type password or client_credentials.
We'll support: =authorization_code= and =refresh_token=.
**** Scopes
Format:
- =<high-level-api>(:<access-type>)?=
- =<high-level-api>(/subset)*(:<access-type>)?=
Examples:
- openid
- email
- collect
- collect:read
- iroh-int/observe (read)
- enrich:write
- global-intel
Meaningful:
- deliberations
- enrichment
- private-intel (read/write)
- global-intel (read/write)
- references (read)
- response (write)
- deliberate, describe, observe
.
*** =/approve=
The User can approve access to an App.
The App get back a Auth Code.
*** =/refuse=
The User can refuse or revoke access to an App.
*** =/token=
The App can ask to refresh tokens.
Tokens returned must be "short" lifetime JWT.
** OAuth2 in IROH-Auth Spec RFC second pass
*** Vocabulary
- Roles
+ resource owner: has the ability to grant access to a protected resource
+ resource server: host of the protected resources
+ client: app making requests to resources
+ authorization server: server issuing access token to the client
- Authorization Grant: creds representing resource owner authorization
- Authorization Code: client redirect resource owner to auth server which in
turn redirect the resource owner back to the client with the Auth code
- Access Token: creds used to access protected resource
- Refresh Token: creds to obtain access tokens
- Redirects (generally 302, but up to server)
*** Client Registration
- not really part of the spec. It is up to us to find a way to add a list of
authorized clients, accepted redirection URIs, etc...
- Client Type
+ confidential: private server
+ public: executing itself on some device used by the resource owner
- Client Identifier
+ provided by the authorization server to the client
+ It is not secret
+ Unique
- Client password
can be used via Basic Auth, or in req params: ~client_id=...&client_secret=...~
Auth server MUST protect agains brute force attacks
#+BEGIN_SRC HTTP
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www.form-urlencoded
grant_type=refresh_token&refresh=...&client_id=...&client_secret=...
#+END_SRC
OAuth2 doesn't support unregistered clients
*** Protocol Endpoints
Two auth server endpoints:
- Authorization endpoint: used by the client to obtain authorization from the
resource owner via redirection
- Token endpoint: used by the client to exchange an authorization grant for an
access token, typically with client auth.
Client endpoint:
- Redirection endpoint: used by the auth server to return responses containing
auth creds to the client via the resource owner user-agent
**** Authorization Endpoint
- MUST ignore unrecognized parameters
- MUST not accept repeated params
Client must inform the client of the =response_type=:
- must be set to ~code~ for requesting auth code
- must be set to ~token~ for implicit grant
**** Redirection Endpoint
After completing its interaction with the resource owner, the auth server
directs the resource owner's user-agent to the client.
The redirection URI MUST NOT include a fragment component.
Registration requirement: the auth server MUST require the public and
confidential clients to register their redirection endpoint.
For our usage: the end point must use TLS (https) and also there should be a
single URI per client.
If an auth fails due to missing, invalid or mismatching redirection URI.
The Auth Server should inform the resource owner without redirection.
**** Scope
An unordered list of space-delimited, case-sensitive strings.
The scopes are defined by the auth-server.
If requested scopes by the client are different by the ones granted by the auth
server. The auth server must return the granted scopes as a response parameter.
*** Obtaining Authorization
4 different Grants:
- authorization code
- implicit (no)
- resource owner creds (no)
- client creds (no user, direct client to IROH)
- an extension for more grant types.
**** Code Grant
Used to obtain both access token & refresh tokens.
Optimized for confidential clients.
1. client construct the request URI with the following params:
+ ~response_type~ REQUIRED. Must be ~code~.
+ ~client_id~
+ ~redirect_uri~ (OPTIONAL)
+ ~scope~ (OPTIONAL)
+ ~state~ (RECOMMENDED)
Example:
#+BEGIN_SRC
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.co
#+END_SRC
2. Authorization Response. If auth is granted, then the auth server issues an
authorization code and delivers it to the client by adding the following
parameters to the query component of the redirection URI using the
"application/x-www-form-urlencoded" format.
+ ~code~ REQUIRED. auth code generated. Must expire shortly (10 min
recommended) and shouldn't be used more than once. If the code is used more
than once, should revoke all tokens previously issued based on that
authorization code.
+ ~state~ REQUIRED. Same value as the client provided.
3. Client makes a request to the token endpoint. Should contains the following params:
+ ~grant_type~ REQUIRED. must equal to ~authorization_code~.
+ ~code~ REQUIRED. The auth code received.
+ ~redirect_uri~ REQUIRED. Same as in the authorization request.
+ ~client_id~ REQUIRED. If the client is not authenticating with the auth server.
Example:
#+BEGIN_SRC
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
#+END_SRC
4. Access Token Response.
If the access token is valid and authorized, the auth server issues an access
token and optional refresh token.
Example:
#+BEGIN_SRC
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
#+END_SRC
** OAuth2 Provider Epic
https://github.com/threatgrid/iroh/issues/1349
*** Functional Spec
We want 3rd party to be able to use our APIs (IROH + AMP Global Intel) by making
an OAuth2 Provider.
*** Tasks
See next sections for technical details.
=[#A]=, =[#B]=, =[#C]= are priority order to be able to test the OAuth system
before finishing all the tasks:
- =[#A]= Be able to provide keys to access our API
- =[#B]= Be able to migrate Visibility to OAuth2
- =[#C]= Support revocations, restrictions, etc...
Task without any set priority are lower priority.
*[[client-db][Client DB]]*:
- [ ] Write SQL store
- [ ] =[#C]= Write a service to manage clients
- [ ] =[#C]= Write routes restricted to IROH-Admins to manage OAuth2 clients
- [ ] =[#C]= POST =/clients= (the server sets the ~:id~ and returns the ~:password~
in clear text, in the DB the password should be encrypted).
- [ ] =[#C]= GET =/clients= (the ~:password~ field should be obfuscated)
- [ ] =[#C]= GET =/clients/:id= (the ~:password~ field should be obfuscated)
- [ ] =[#C]= PUT =/clients/:id= to revoke a client access (the ~:password~ field should be obfuscated)
- [ ] =[#C]= DELETE =/clients/:id= to revoke a client access (the ~:password~ field should be obfuscated)
*[[token-db][Authorization DB]]*:
- [ ] =[#B]= Write a service to manage "apps" for a resource owner
- [ ] =[#B]= Write routes to manage "apps" for a resource owner.
The =refresh-token= field should always be hidden or obfuscated.
- [ ] =[#B]= GET =/oauth/apps= returns the list of authorized apps
- [ ] =[#B]= GET =/oauth/apps/:app-id= return the authorized app informations
- [ ] =[#B]= DELETE =/oauth/apps/:app-id= remove the authorized app, further refresh
token queries should fail.
*[[user-db][User DB]]*:
- [ ] =[#C]= Write a Service to manage Users with the following methods:
- [ ] =[#C]= Create an user and generate its id. To be used for new login of still unkown user.
- [ ] =[#C]= search an user by internal id or 3rd party User id (typically AMP user id)
- [ ] =[#C]= revoke an user
- [ ] =[#C]= change scopes of an user
- [ ] =[#C]= Write routes restricted to IROH-Admins to manage Users
- [ ] =[#C]= GET =/users= returns a list of users
- [ ] =[#C]= GET =/users/:user-id= returns the specific user infos
- [ ] =[#C]= PUT =/users/:user-id= update an user, either revoke access or change scope
*[[routes][OAUTH2 Routes]]*:
- [ ] =/authorize= endpoint (should be behing the classic JWT protection)
- [ ] =[#A]= Support for authorization code grant
- [ ] =[#B]= Support for client creds grant
- [ ] Support implicit grant (close the current workflow with /login)
- [ ] =[#A]= =/token= endpoint
*[[middleware][Protected Resource Middleware]]*:
- [ ] =[#A]= Update the JWT middleware to only accept access-tokens
- [ ] =[#B]= Add a :scopes to compojure-api routes to filter access to JWT granting those scopes
- [ ] =[#B]= Update all routes to add a :scopes (cf. [[scopes][scopes]])
*[[frontend][Frontend]]*:
- [ ] =[#C]= Update the frontend to use the new OAuth2 routes.
- [ ] Create a dahsboard to help an user to revoke apps
- [ ] Create an IROH-Admin only dahsboard to manage clients (create, revoke, etc...)
- [ ] Create an IROH-Admin only dahsboard to manage users (revoke, etc...)
*[[doc][Documentation]]*:
- [ ] Documentation for making trusted daemons (authorization code grant)
- [ ] Documentation for frontend dev (implicit grant)
- [ ] Documentation for scripts (client creds grant)
*** Technical Spec
Write an OAuth2 provider.
Specificity of our OAuth2 provider.
- codes, access-tokens & refresh-tokens should be JWT.
Because JWT expires, and we can control how often we check their status
(revoked for example) server side.
Supported Grants (by priority order):
- ~authorization code~ grant
- ~implicit~ grant (for Visibility/iroh-ui) (similar to today =/login=)
- ~client creds~ grant
**** Client DB
<<client-db>>
We need to be able to add new OAuth2 "clients".
And we must be able to revoke a client.
So we need to add another store for clients.
Actually we shouldn't store those informations in ES.
We need to write an SQL backed CRUD store.
More specifically we'll use postgresql.
There should be another web-service exposing routes only for IROH admins.
*Question*: How should we keep client password?
*Proposal*: Present password in cleartext to the "creator" only once but save
the password using bcrypt.
A client MUST have a ~client-type~, a ~client-id~ and a ~client-password~.
Proposed internal representation:
#+BEGIN_SRC clojure
(s/defschema CRUDMetas
{:created-at s/DateTime
(s/optional-key :updated-at) s/DateTime
(s/optional-key :activated-at) s/DateTime
(s/optional-key :approved-at) s/DateTime
(s/optional-key :enabled-at) s/DateTime
(s/optional-key :blocked-at) s/DateTime})
(def Scope s/Str) ;; MUST NOT contain any space see the Scope section
(def URI s/Str) ;; shouldn't contains any fragment '#...', space or '..'
;; HIGHLY RECOMMENDED should be HTTPS
(defschema Client
(st/merge {:client-type (s/enum :confidential :public)
:grants #{(s/enum :auth-code :implicit :client-creds)}
:redirects #{URI}
:id s/Str
:password s/Str
:name s/Str
:scopes #{Scope}
:approved? s/Bool
:enabled? s/Bool}
CRUDMetas)
#+END_SRC
For example:
#+BEGIN_SRC clojure
(def threatgrid-client
{:client-type :confidential
:grants :auth-code
:redirects ["https://threatgrid.cisco.com/"]
:id "5fb04b9a-faad-11e7-8c3f-9a214cf093ae"
:password "70D3C005435E0F1C75A622C6C5AE92DB395A9E3140DE6980AC733AC9316AC0AE"
:name "ThreatGrid"
:scopes ["response" "enrich" "iroh-collect" "ui-settings" "ctia"]
:approved? true
:enabled? true
:created-at "2018-01-20T10:04:33"
:updated-at "2018-01-20T10:04:33"
:enabled-at "2018-01-20T10:04:33"
:activated-at "2018-01-20T10:04:33"
:approved-at "2018-01-20T10:04:33"})
#+END_SRC
**** User DB
<<user-db>>
We need to have an OAuth2 oriented Internal User DB.
For example to be able to change the scopes or simplly to revoke access to some
users.
Even if in the future we'll need a more complex User DB, for now we only need to
keep track of relation between an user-id for some 3rd party and an internal
user-id.
#+BEGIN_SRC clojure
(s/def IdPMapping
(st/merge
{:idp (s/enum :amp :threatgrid)
:user-id s/Str
:org-id s/Str}
{s/Any s/Any}))
(s/def UserClaims
{"cisco.com/iroh/user/id" s/Str
"cisco.com/iroh/user/name" s/Str
"cisco.com/iroh/org/id" s/Str
"cisco.com/iroh/org/name" s/Str
"cisco.com/iroh/roles" [s/Str]
;; see IROH-Auth JWT fields (remove all time-related ones)
})
(s/def User
(st/merge
{:enabled? s/Bool
:external-infos #{IdPMapping}}
PartialJWT
CRUDMetas))
#+END_SRC
**** Authorization DB / App DB
<<token-db>>
A refresh token are credentials representing the access granted by an user to
some client.
☞ Refresh tokens are typically long-lasting credentials used to request additional
access tokens, the refresh token is bound to the client to which it was issued.
(See https://tools.ietf.org/html/rfc6749#section-6)
So we should provide a mean for an user to revoke those accesses.
Remark the db should be populated via the =/authorize= endpoint.
There shouldn't be any way for an user to create or update an app, only delete.
Example:
#+BEGIN_SRC clojure
(s/defschema OAuthApp
{:id s/Str
:refresh-token s/Str
:client-id s/Str
(s/optional-key :client-name) s/Str
:authorized-date s/DateTime
:scopes #{Scope}})
#+END_SRC
**** OAUTH2 Routes
<<routes>>
We need to support the Code Grant so here is details about the workflow.
Note a lot of important details are in the RFC about how to handle those routes
securely.
Also, examples were modified so that the tokens are JWT.
***** Authorization Code Grant Worflow
The full details can be seen in the RFC: https://tools.ietf.org/html/rfc6749#section-4.1
Here some details were changed to adapt to our specifities (like using JWT).
The workflow is used to obtain both *access token* & *refresh tokens*.
Optimized for confidential clients.
1. client construct the request URI and redirect the
resource owner's user-agent to =/authorize= with the following params:
+ ~response_type~ REQUIRED. Must be ~code~.
+ ~client_id~
+ ~redirect_uri~ (OPTIONAL)
+ ~scope~ (OPTIONAL)
+ ~state~ (RECOMMENDED)
Example:
#+BEGIN_SRC
GET /authorize?response_type=code
&client_id=5fb04b9a-faad-11e7-8c3f-9a214cf093ae
&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.co
#+END_SRC
2. Authorization Response. If auth is granted, then the auth server issues an
authorization code and delivers it to the client by adding the following
parameters to the query component of the redirection URI using the
"application/x-www-form-urlencoded" format.
+ ~code~ REQUIRED. auth code generated. Must expire shortly (10 min
recommended) and shouldn't be used more than once. If the code is used more
than once, should revoke all tokens previously issued based on that
authorization code.
+ ~state~ REQUIRED. Same value as the client provided.
3. Client makes a request to the token endpoint. Should contains the following params:
+ ~grant_type~ REQUIRED. must equal to ~authorization_code~.
+ ~code~ REQUIRED. The auth code received.
+ ~redirect_uri~ REQUIRED. Same as in the authorization request.
+ ~client_id~ REQUIRED. If the client is not authenticating with the auth server.
Example:
#+BEGIN_SRC
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=eyJh...SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
#+END_SRC
4. Access Token Response.
If the access token is valid and authorized, the auth server issues an access
token and optional refresh token.
Example:
#+BEGIN_SRC
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"eyJh...2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"eyJh..tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
#+END_SRC
*Refres Token*: for this PR, refreshing a token shouldn't create another
=refresh-token=. That way our client won't need to update their credentials. But
that is an option to keep in mind.
***** IROH Specificities
In IROH we don't have internal user login/password.
But we have a =/login= route that redirect with a =jwt= containing credentials.
So if we reach =/authorize= with such a valid =jwt= then we could continue by
using the user creds, if on the other hand we don't have such =jwt= the
=/authorize= should make a "double" redirection.
One to =AMP= (or =TG= in the future) login page and then the user-agent should
be redirected with the same URI but this time, a JWT should be provided in the
Headers if possible.
And then, if the =authorize= is validated, it will redirect to the client.
***** Tokens/Code format
One easy way to handle the lifetime of tokens and code is to use JWT.
During the code grant, the call to =/authorize= should redirect the user to some
page where the user interact and grant the access to the client. The output of
this call, the user is redirected via its user-agent with a short-living "code".
#+BEGIN_SRC clojure
(s/defschema IROHJWT ...) ;; see iroh-auth current JWT format
(s/defschema OAuthAuthorizeCode
(st/merge IROHJWT
{:kind (s/enum :grant)
:grant-type (s/enum :authorization-code)
:client-id s/Str}))
#+END_SRC
Such JWT MUST be REFUSED if used directly to access a protected resource.
Such =OAuthAuthorizedCode= should only be used to access the =/token= endpoint.
The =/token= endpoint will in turn returns two JWT.
The /access-token/ and the /refresh-token/.
- /access-tokens/ are the only token which grant access to protected resources.
- /refresh-tokens/ can be used to get /access-tokens/ without resource-owner interaction.
Proposed schemas:
#+BEGIN_SRC clojure
(s/defschema OAuthAccessToken
(st/merge IROHJWT
{:kind (s/enum :access-token)
:user-id s/Str
:client-id s/Str
:scopes #{Scope}))
(s/defschema OAuthRefreshToken
(st/merge IROHJWT
{:kind (s/enum :refresh-token)
:app-id s/Str
:user-id s/Str
:client-id s/Str
:scopes #{Scope}}))
#+END_SRC
So when asking for a refresh token we could check the statuses of the user,
the client and the refresh-token.
**** Protected Resource Middleware
<<middleware>>
The current JWT middleware should be modified to only accept =:access-token= JWT
for protected resources routes.
There should more specific JWT system to handle the =/authorize= and =/token= routes.
**** Frontend
<<frontend>>
***** Become OAuth2 compliant
Visibility/IROH-UI should also become a "client".
And thus some minor changes should be done.
Instead of going to =/login= Visibility should access =/authorize= with the
following parameters:
- ~response_type~ value MUST be ~token~
- ~client_id~ the client id for visibility
- ~redirect_uri~ (as it is today)
- ~scope~ (the list of scopes Visibility need to access)
- ~state~ (the inner state of the app, the parameter as another name today)
The response format will also be slightly changed.
The fragment of the URL will contain:
- ~access_token~ (previously was ~jwt~)
- ~token_type~ should be ~bearer~
- ~scope~ OPTIONAL if identical to the scope requested by the client; REQUIRED otherwise
- ~state~ the state provided in the request
It is up to the server to make the same workflow than with the previous =/login=
***** App Dahsboard
Make an app dashboard to help users manage their authorized apps.
It should be inspired by the features of the API.
Only ability to revoke/delete some app.
***** IROH-Admin only dahsboard to manage clients
Have a dashboard for IROH-Admin only to manage clients.
Typically block accesses to a client but also change the client properties.
***** Create an IROH-Admin only dahsboard to manage users (revoke, etc...)
Have a dashboard for IROH-Admin only to manage users and be able to block some.
**** Scopes
<<scopes>>
While we can easily update scopes in the future.
We should start with a sane convention.
A scope should match the following regex: ~\w+[\w\d_-]*(/\w+[\w\d_-]*)*(:\w+[\w\d_]*)?~
A nicer way to look at it is that it should have the following format:
- =<high-level-api>=
- =<high-level-api>(:<access-type>)?=
- =<high-level-api>(/subset)*(:<access-type>)?=
Mainly identifier with potential =:= followed by another identifier.
The main format is: =<api>= or =<api>:<access-restriction>=.
For example: ~enrich~, ~enrich:read~, ~enrich/observe~ or ~enrich/observe:read~.
In order to filter access, if a JWT contains the following scopes:
#+BEGIN_SRC clojure
["ui-settings","enrich:read","collect/inspect"]
#+END_SRC
The mean the JWT can access all the routes with the following scopes:
- ~ui-settings:read~
- ~ui-settings:write~
- ~enrich/observe:read~
- ~enrich/enrich:read~
- ~enrich/deliberate:read~
- ~enrich/settings:read~
- ~collect/inspect:read~
But shouldn't access the following scopes:
- ~auth/client-mgmt:write~
- ~enrich/enrich:write~
- ~enrich/settings:write~
- ~collect/config~
Here is the exhaustive list of our exposed web services and the proposed scope prefix:
| route | scope |
|-------------------+-------------|
| /iroh-ui-settings | ui-settings |
| /iroh-auth | auth |
| /iroh-auth-mgmt | auth/mgmt |
| /fake-iroh-auth | auth/fake |
| /iroh-enrich | enrich |
| /iroh-response | response |
| /iroh-inspect | inpect |
When the route change some inner state (like writing to some store/db, then we
should use the ~write~ access-restriction. Otherwise the access restriction
should be ~read~.
Depending on the routes we should also add subsets. Typically:
- ~auth/mgmt/jwt-revoke~
- ~auth/mgmt/saml-org-whitelist~
*Scope Accesses*: the scopes granted to an access-token MUST always be a
subset of the intersection of the scopes of the client and the scopes of the
user.
**** Documentation
<<doc>>
We should write a clear documentation to help 3rd party developer use our API
via OAuth2.
** OAuth2 Epics (3rd pass)
*** SPA compatible OAuth2
Provide a way for any website to use OAuth2 and make call to IROH API. Typically
make it easy to create a generic casebook lib or even perhaps a web browser
plugin that could work on any website.
**** Issues
- [ ] Support Auth-code without client password
- [ ] Support CORS that use informations from the access token
- [ ] Documentation:
- [ ] Write a document/blog post for developers
- [ ] Make a demo website if possible using a 3rd party lib like hello.js
- [ ] Provide a lib (for example a module for hello.js)
*** User's made OAuth2 clients
Users should be able to create OAuth2 clients with some limitations regarding
response and passwordless client.
IROH Admin users should create OAuth2 clients without scope limitation and
should be able to create public clients (destined for SPA).
**** Issues
- [ ] Decide if we authorize any user to create a public OAuth2 client that are
needed for SPA clients (see https://tools.ietf.org/html/rfc6749#section-2.1)
- [ ] User can access a webpage to manage their OAuth app grants #iroh-ui
- [ ] Provide the ability for user to create OAuth2 clients
- [ ] Forbid any client to require any `response/*:write` scope
- [ ] Provide urls to make all response using HTLM pages generated by Visibility
*** Internal User Representation
Currently all the data about an user is provided via the generation of IROH Auth JWT.
This kind of limit our ability to manage user access.
For example, while we can currently revoke access to any user given its id it would be
difficult to limit an user scope.
Also without an internal user representation it is not possible to merge
different IdP for the same user.
In the future it might also be useful to have Visibility only user preferrences.
**** Issues
- [ ] Write a documentation about how we should manage internal representation.
Also how to deal with default org, preferred IdP, etc...
- [ ] Write IROH admin-only, routes and service to
- create an user and generate its id
- search an user by either internal id or other 3rd party user id (typically
AMP or TG user id)
- revoke access to an user
- change authorized scopes of an user
*** OAuth2 Client Credentials Grant
Support OAuth2 Client Credentials grant which is really useful for scripts.
Mainly the workflow should be:
1. The user create a new confidential client with only client credential grant.
2. The user is returned with a client-id / client-password
3. The script can use those client creds to retrieve access only for that user.
- [ ] =[#C]= Write a Service to manage Users with the following methods:
- [ ] =[#C]= Create an user and generate its id. To be used for new login of still unkown user.
- [ ] =[#C]= search an user by internal id or 3rd party User id (typically AMP user id)
- [ ] =[#C]= revoke an user
- [ ] =[#C]= change scopes of an user
- [ ] =[#C]= Write routes restricted to IROH-Admins to manage Users
- [ ] =[#C]= GET =/users= returns a list of users
- [ ] =[#C]= GET =/users/:user-id= returns the specific user infos
- [ ] =[#C]= PUT =/users/:user-id= update an user, either revoke access or change scope
**** Issues
- [ ] Support Client Credentials Grant (for confidential client only, see
https://tools.ietf.org/html/rfc6749#section-4.4)
***** Client DB
- [ ] =[#C]= Write a service to manage clients
- [ ] =[#C]= Write routes to manage OAuth2 clients
- [ ] =[#C]= POST =/clients= (the server sets the ~:id~ and returns the ~:password~
in clear text, in the DB the password should be encrypted).
- [ ] =[#C]= GET =/clients= (the ~:password~ field should be obfuscated)
- [ ] =[#C]= GET =/clients/:id= (the ~:password~ field should be obfuscated)
- [ ] =[#C]= PUT =/clients/:id= to revoke a client access (the ~:password~ field should be obfuscated)
- [ ] =[#C]= DELETE =/clients/:id= to revoke a client access (the ~:password~ field should be obfuscated)
***** User DB
- [ ] =[#C]= Write a Service to manage Users with the following methods:
- [ ] =[#C]= Create an user and generate its id. To be used for new login of still unkown user.
- [ ] =[#C]= search an user by internal id or 3rd party User id (typically AMP user id)
- [ ] =[#C]= revoke an user
- [ ] =[#C]= change scopes of an user
- [ ] =[#C]= Write routes restricted to IROH-Admins to manage Users
- [ ] =[#C]= GET =/users= returns a list of users
- [ ] =[#C]= GET =/users/:user-id= returns the specific user infos
- [ ] =[#C]= PUT =/users/:user-id= update an user, either revoke access or change scope
***** Frontend
- [ ] Create an admin UI for any user to manage OAuth clients
*** IROH Admin Dashboard
It would be very effective to have a dashboard instead of just using the
swagger-ui. The dashboard would make it easy to centralize the access of all
informations as well as administration tasks.
Typically:
- be able to see some IROH logs filtered by some keywords, and be able
to revoke an user or an OAuth client. Also be able to change the scopes of some
clients.
- Provide the ability to force all user to be prompted to grant access again to
some client, etc...
*** OAuth2 Enhancements
Many OAuth2 feature should be enabled in order to provide the best security.
- [ ] Automatically revoke refresh token access if the code was used more than once.
Archived entries from file /Users/yaesposi/.deft/Cisco.org.gpg
* [#C] Scopes Dictionary
:PROPERTIES:
:ARCHIVE_TIME: 2019-01-09 Wed 10:53
:ARCHIVE_FILE: ~/.deft/Cisco.org.gpg
:ARCHIVE_OLPATH: Epics
:ARCHIVE_CATEGORY: Cisco.org
:END:
Regarding access right of API consumer this is enforced via scopes.
There are low-level scopes. Mostly one for each route. To help represent
coherent groups the scopes are organized as a tree whose leaves are tagged
either by read or write.
For example if an user has the scopes ~["foo/bar:read" "baz"]~
He'll could access all routes with those scopes:
- ~foo/bar:read~
- ~foo/bar/baz:read~
- ~foo/bar/baz/quux:read~
- ~baz:write~
- ~baz/x/y:write~
But he won't be granted the access to:
- ~bad:read~
- ~foo/bar:write~
- ~foo/bar/baz:write~
The problem with this organisation is that it's somehow too technical. This is
why we need to introduce high-level abstracts scopes to give meaningful names to
precise subsets of route access.
To that end we should provide a dictionnary (with schema
~{s/Str {:scopes #{s/Str}} :name s/Str :description s/Str}~):
#+BEGIN_SRC clojure
{"importer" {:scopes #{"collect" "ctia:read"}
:name "Importer"
:description "This client would like to be able to import events into
your private intel store,
and needs some limited read permissions as well"}
...
}
#+END_SRC
Technically it would simply mean that if an user has the scope "importer" we'll look into that
dictionnary to provide him the technical scopes.
Furthermore we'll be able to look into this dictionary to provide a meaninful name and description
to the user when he's asked to grant some access to some 3rd party app (OAuth client).
Archived entries from file /Users/yaesposi/.deft/Cisco.org.gpg
* DONE Document for Raghavaiah
CLOSED: [2018-11-28 Wed 18:01]
:PROPERTIES:
:ARCHIVE_TIME: 2019-01-09 Wed 10:54
:ARCHIVE_FILE: ~/.deft/Cisco.org.gpg
:ARCHIVE_CATEGORY: Cisco.org
:ARCHIVE_TODO: DONE
:END:
** Frank's proposal; Auth config untangling
IROH Auth and SSE staging config changes to correctly link environments and improve naming
*** INT
**** idb-amp-staging / selector: amp
This is actually pointing to QA1 on the AMP side. We should name it as such.
- CTR
- Change identifier to `idb-amp-qa1`
- Change name to `AMP QA1`
- Change selector to `amp-QA1`
- SSE IDB
- Change selector to `amp-qa1`
**** idb-tg-staging / selector: tg
This is TG INT, just need a rename
- CTR
- Change identifier to `idb-tg-int`
- SSE IDB
- CHange selector to `tg-int`
*** TEST
**** idb-amp-staging / selector: amp
This needs to go to AMPs SDC environment instead. We'll need a new auth provider setup on the SSE side for AMP SDC
- CTR
- Change identifier to `idb-amp-sdc`
- Change name to `AMP SDC`
- Change selector to `amp-sdc`
- SSE IDB
- New auth provider with URL: https://auth-ext.qa1.immunet.com/
- Selector `amp-sdc`
**** idb-tg-staging / selector: tg
This will need to point at the TG TEST environment, not INT. It'll also need a new auth provider be created in the IDB
- CTR
- Change identifier to `idb-tg-test`
- Change name to `Threat Grid TEST`
- Change selector to `tg-test`
- SSE IDB
- New auth provider with URL: https://test.threatgrid.com/ (Frank to create new oauth2 client if needed)
- Selector`tg-test`
** Proposal
To help people manage all the IDB clients and connection we would like to follow a stricter naming convention.
There are many different named entities:
- IROH IdP id
- IDB selector
- IROH-UI button label
The IROH IdP id is used in the =redirect_uri= that should be configured in the
IDB client.
Also there are two different IDB environment. IDB prod and IDB stage.
Each client should also point to some IdP environment, typically, AMP NAM Prod,
or AMP QA1, or AMP SDC.
The namin convention should make it clear what IDB instance is used as well as
with IdP it targets, in particular we should make each region explicit.
Note all point prefixed by =IDB= are the information needed by the SSE/IDB team.
*** INT
**** AMP
Note: I think it should point to AMP prod as before to prevent the use of the VPN
to login to INT
- IROH IdP id: idb-stage-amp-nam
- IDB env: Stage
- IDB selector: idb-stage-amp-nam
- IDB redirect uris:
- https://visibility.int.iroh.site/iroh/iroh-auth/login/idb-stage-amp-nam/answer
- https://localhost:5443/callback
- IDB IdP Target: https://auth.amp.cisco.com/auth/session/new
- IROH-UI button label: Cisco Security
**** TG
- IROH IdP id: idb-stage-tg-int
- IDB env: Stage
- IDB selector: idb-stage-tg-int
- IDB redirect uris:
- https://visibility.int.iroh.site/iroh/iroh-auth/login/idb-stage-tg-int/answer
- https://localhost:5443/callback
- IDB IdP Target: https://int.threatgrid.com/oauth2/authorize
- IROH-UI button label: Cisco Security
*** PROD NAM
**** AMP
- IROH IdP id: idb-amp-nam
- IDB env: Prod
- IDB selector: idb-amp-nam
- IDB redirect uris:
- https://visibility.amp.cisco.com/iroh/iroh-auth/login/idb-amp-nam/answer
- IDB IdP Target: https://auth.amp.cisco.com/auth/session/new
- IROH-UI button label: Cisco Security
**** TG
- IROH IdP id: idb-tg-nam
- IDB env: Prod
- IDB selector: idb-tg-nam
- IDB redirect uris:
- https://visibility.amp.cisco.com/iroh/iroh-auth/login/idb-tg-nam/answer
- https://visibility.apjc.amp.cisco.com/iroh/iroh-auth/login/idb-tg-nam/answer
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-tg-nam/answer
- IDB IdP Target: https://panacea.threatgrid.com
- IROH-UI button label: Threat Grid
*** PROD EU
**** AMP
- IROH IdP id: idb-amp-eu
- IDB env: Prod
- IDB selector: idb-amp-eu
- IDB redirect uris:
- https://visibility.eu.amp.cisco.com/iroh/iroh-auth/login/idb-amp-eu/answer
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-amp-eu/answer
- IDB IdP Target: https://auth.eu.amp.cisco.com/auth/session/new
- IROH-UI button label: Cisco Security
**** TG
- IROH IdP id: idb-tg-eu
- IDB env: Prod
- IDB selector: idb-tg-eu
- IDB redirect uris:
- https://visibility.eu.amp.cisco.com/iroh/iroh-auth/login/idb-tg-eu/answer
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-tg-eu/answer
- IDB IdP Target: https://panacea.threatgrid.eu
- IROH-UI button label: Threat Grid
*** PROD APJC
**** AMP
- IROH IdP id: idb-amp-apjc
- IDB env: Prod
- IDB selector: idb-amp-apjc
- IDB redirect uris:
- https://visibility.apjc.amp.cisco.com/iroh/iroh-auth/login/idb-amp-eu/answer
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-amp-apjc/answer
- IDB IdP Target: https://auth.apjc.amp.cisco.com/auth/session/new
- IROH-UI button label: Cisco Security
**** TG
This one is the same as the TG for prod. TG doesn't have an APJC endpoint for login.
- IROH IdP id: idb-tg-nam
- IDB env: Prod
- IDB selector: idb-tg-nam
- IDB redirect uris:
- https://visibility.amp.cisco.com/iroh/iroh-auth/login/idb-tg-nam/answer
- https://visibility.apjc.amp.cisco.com/iroh/iroh-auth/login/idb-tg-nam/answer
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-tg-nam/answer
- IDB IdP Target: https://panacea.threatgrid.com
- IROH-UI button label: Threat Grid
*** TEST
For test, we should want to be able to login through many different envs to
check none is broken or a future change won't break our login.
So the "classical integration with test envs".
**** TEST IdPs
***** AMP SDC
- IROH IdP id: idb-stage-amp-sdc
- IDB env: Stage
- IDB selector: idb-stage-amp-sdc
- IDB redirect uris:
- https://visibility.test.iroh.site/iroh/iroh-auth/login/idb-stage-amp-sdc/answer
- https://localhost:5443/callback
- IDB IdP Target: https://auth-ext.qa1.immunet.com/
- IROH-UI button label: AMP SDC
***** TG Test
- IROH IdP id: idb-stage-tg-test
- IDB env: Stage
- IDB selector: idb-stage-tg-test
- IDB redirect uris:
- https://visibility.int.iroh.site/iroh/iroh-auth/login/idb-stage-tg-test/answer
- https://localhost:5443/callback
- IDB IdP Target: https://test.threatgrid.com/oauth2/authorize
- IROH-UI button label: Cisco Security
**** Prod Logins
Instead of duplicate the infos, we should copy all buttons from the 3 prod regions.
Note it will only create 5 buttons instead of 6 because there is no TG APJC login page.