mik-laj opened a new issue #11305:
URL: https://github.com/apache/airflow/issues/11305


   # Why? 
   
   Users expect integration with various Identity Aware Proxies (IAP) that 
provide authorization.  The use of such proxies brings many benefits.
   - facilitates the enforcement of the company's policy by:
      - central access management, depending on the proxy selected, we can 
support various authentication protocols, including LDAP, Google IAM, SAML, 
OpenID
      - audibility - can write additional metadata about the operations 
performed by users
   - No need to keep secrets in a container that can execute user code. All the 
necessary user info is provided in a push model.
   - One proxy can be used to protect multiple applications, so it is code that 
meets higher security standards. They are often regularly audited. The in-app 
part is very simple and easier to audit.
   
   Besides, it can make using LDAP with Airflow much easier. Deficiencies in 
the implementation of LDAP for Airflow will no longer be a problem for our 
users e.g. https://github.com/dpgaspar/Flask-AppBuilder/issues/956) 
   
   I think we should prepare implementations for some of the most popular 
products:
    - [Louketo Proxy](https://github.com/louketo/louketo-proxy) (formerly 
Keycloak Gateway)
    - [Google Identity Aware Proxy (IAP)](https://cloud.google.com/iap)
    - [Promerium](https://www.pomerium.com/)
   
   This will be an example for other uses for other products as well.
   
   # How?
   
   In order to accomplish this task for each supported proxy, we need to 
prepare two authorization checks - one for Web UI, one for API. 
   
   Creating your own API auth backend is described in our documentation:  
https://airflow.readthedocs.io/en/latest/security/api.html#roll-your-own-api-authentication
   
   Creating an integration with Flask App Builder is a bit worse described, but 
in our case, we can extend 
[`REMOTE_USER`](https://flask-appbuilder.readthedocs.io/en/latest/security.html)
 to support product-specific headers.
   
   To do this, create a new view based on the 
`flask_appbuilder.security.views.AuthView` class, and then set it as an 
`authremoteuserview` attribute in the 
`airflow.www.security.AirflowSecurityManager` class.  You can use the 
[`flask_appbuilder.security.views.AuthRemoteUserView` 
class](https://github.com/dpgaspar/Flask-AppBuilder/blob/5806f9ff66a26eb287759f890051060060e55e53/flask_appbuilder/security/views.py#L732)
 as a template.
   
   Below is a minimal example of the `webserver_config.py` file (you should 
save it to `~/airflow/config/`) that provide authorizations using the 
`X-Auth-Username` header.  The goal is to support more vendor-specific headers
   ```python
   
   from flask import get_flashed_messages, request, redirect, flash
   from flask_appbuilder import expose
   from flask_appbuilder._compat import as_unicode
   from flask_appbuilder.security.views import AuthView
   from flask_login import login_user, logout_user
   
   from airflow.www.security import AirflowSecurityManager
   
   
   class CustomAuthRemoteUserView(AuthView):
       login_template = ""
   
       @expose("/login/")
       def login(self):
           if g.user is not None and g.user.is_authenticated:
               return redirect(self.appbuilder.get_url_for_index)
   
           username = request.environ.get("X-Auth-Username")
           if username:
               user = self.appbuilder.sm.auth_user_remote_user(username)
               if user is None:
                   flash(as_unicode(self.invalid_login_message), "warning")
               else:
                   login_user(user)
           else:
               flash(as_unicode(self.invalid_login_message), "warning")
   
           # Flush "Access is Denied" flash messaage
           get_flashed_messages()
           return redirect(self.appbuilder.get_url_for_index)
   
       @expose("/logout/")
       def logout(self):
           logout_user()
           return redirect("/oauth/logout")
   
   
   class CustomAirflowSecurityManager(AirflowSecurityManager):
       authremoteuserview = CustomAuthRemoteUserView
   
   
   SECURITY_MANAGER_CLASS = CustomAirflowSecurityManager  # pylint:
   ```
   Invoking function `get_flashed_messages` clears the "Access denied" flash 
message that appears when the user is redirected from `/` to `/login`. This is 
not included with the FAB, but is needed in Airflow.
   
   In the case of Louketo/Keycloak, we should support the following headers: 
   
   - X-Auth-Email
   - X-Auth-Family-Name
   - X-Auth-Given-Name
   - X-Auth-Groups
   - X-Auth-Roles
   - X-Auth-Username
   
   In the case of Google IAP, we should use the JWT signed header: 
https://cloud.google.com/iap/docs/signed-headers-howto
   In the case of Promerium, we should use the JWT signed header - 
`X-Pomerium-Jwt-Assertion: `: 
https://www.pomerium.io/docs/topics/getting-users-identity.html#prerequisites
   
   # Status
   
   - [ ] API support Louketo Proxy
   - [ ] API support Google IAP
   - [ ] API support Promerium
   - [ ] Web UI support Louketo Proxy
   - [ ] Web UI support Google IAP
   - [ ] Web UI support Promerium
   - [ ] Docs for Louketo Proxy
   - [ ] Docs for Google IAP
   - [ ] Docs for Promerium
   
   # Disclaimer
   
   If someone is interested in this task, I will be happy to provide all the 
necessary information and support.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to