diff --git a/dockers/eflows-airflow.docker b/dockers/eflows-airflow.docker index 7afe5e6546803ea5cfa7db66e2ae9707e1549f6c..9aecbbe44211c06058f333977ee63c33648f8e05 100644 --- a/dockers/eflows-airflow.docker +++ b/dockers/eflows-airflow.docker @@ -1,9 +1,9 @@ -FROM apache/airflow:slim-2.5.3-python3.8 +FROM apache/airflow:slim-2.7.1-python3.10 USER root RUN apt update && apt install git -y && apt clean && rm -rf /var/lib/apt/lists/* -COPY ./templates/main.html /home/airflow/.local/lib/python3.8/site-packages/airflow/www/templates/airflow/main.html -COPY ./templates/navbar_right.html /home/airflow/.local/lib/python3.8/site-packages/airflow/www/templates/appbuilder/navbar_right.html -COPY ./templates/img/BMBF_gefoerdert_2017_en.jpg /home/airflow/.local/lib/python3.8/site-packages/airflow/www/static/BMBF_gefoerdert_2017_en.jpg +COPY ./templates/main.html /home/airflow/.local/lib/python3.10/site-packages/airflow/www/templates/airflow/main.html +COPY ./templates/navbar_right.html /home/airflow/.local/lib/python3.10/site-packages/airflow/www/templates/appbuilder/navbar_right.html +COPY ./templates/img/BMBF_gefoerdert_2017_en.jpg /home/airflow/.local/lib/python3.10/site-packages/airflow/www/static/BMBF_gefoerdert_2017_en.jpg USER airflow diff --git a/plugins/unity_integration.py b/plugins/unity_integration.py index bc74decc5937a564b256fc82437983217e6bcdce..65f81e455475cd3afd27279be2a6109fb44d6bd6 100644 --- a/plugins/unity_integration.py +++ b/plugins/unity_integration.py @@ -25,6 +25,14 @@ oauth.register( unity = Blueprint('unity', __name__, url_prefix="/unity") class UnityIntegrationView(AppBuilderBaseView): + ''' + This adds the neccessary routes for a oauth2 login support in addition to the basic_auth provided by airflow. + This is achieved by handling the oauth2 flow fully via the added routes nad using the basic_auth via internal functions. + Once a user has been authenticated, a matching user (via username or email) is either found or created in the airflow basic_auth database. + + This means that the Oauth2 provider needs to be trusted to the same extent that the local user db is trusted. + This can also break on airflow updates without notice, as airflow-internal security functions are used, that are not well-documented and appear to not be intended for this use. + ''' @unity.route('/') @unity.route('/login') @@ -87,6 +95,10 @@ class UnityIntegrationView(AppBuilderBaseView): else: log.error("User creation unsuccessful.") abort(500) + else: + # set role permissions of that user, if it already exists (just take the role from SSO and assign it) + fab_user.role = sec_manager.find_role(role) + sec_manager.update_user(fab_user) # login as that user login_user(fab_user, remember=False) return redirect(url_for("Airflow.index")) diff --git a/requirements.txt b/requirements.txt index 5e2464fb9acc9e25928298d07a3361f45e767cab..2843b999d4993a280a49e3ebdf850bb669103731 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,8 +3,8 @@ urllib3 plyvel webdavclient3 boto3==1.24.32 -apache-airflow[celery]==2.5.3 -apache-airflow[redis]==2.5.3 +apache-airflow[celery]==2.7.1 +apache-airflow[redis]==2.7.1 apache-airflow-providers-ssh apache-airflow-providers-http apache-airflow-providers-sftp diff --git a/templates/navbar_right.html b/templates/navbar_right.html index a3ded7e6346f549382fd556ef590eb4d22d08832..52c188c38c2dceac67f062739c97f7ef97e3f58e 100644 --- a/templates/navbar_right.html +++ b/templates/navbar_right.html @@ -1,91 +1,96 @@ {# - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - #} - - {% macro locale_menu(languages) %} - {% set locale = session['locale'] %} - {% if not locale %} - {% set locale = 'en' %} - {% endif %} - <li class="dropdown"> - <a class="dropdown-toggle" href="javascript:void(0)"> - <div class="f16"><i class="flag {{languages[locale].get('flag')}}"></i><b class="caret"></b></div> - </a> - {% if languages.keys()|length > 1 %} - <ul class="dropdown-menu"> - <li class="dropdown"> - {% for lang in languages %} - {% if lang != locale %} - <a href="{{appbuilder.get_url_for_locale(lang)}}"> - <div class="f16"><i class="flag {{languages[lang].get('flag')}}"></i> - {{languages[lang].get('name')}} - </div></a> - {% endif %} - {% endfor %} - </li> - </ul> - {% endif %} - </li> - {% endmacro %} - - {# clock and timezone menu #} - <li class="dropdown" id="timezone-dropdown"> - <a class="dropdown-toggle" style="display:none" href="#"> - <time id="clock" class="js-tooltip"></time> - <b class="caret"></b> + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + #} + + {% macro locale_menu(languages) %} + {% set locale = session['locale'] %} + {% if not locale %} + {% set locale = 'en' %} + {% endif %} + <li class="dropdown"> + <a class="dropdown-toggle" href="javascript:void(0)"> + <div class="f16"><i class="flag {{languages[locale].get('flag')}}"></i><b class="caret"></b></div> </a> - <ul class="dropdown-menu" id="timezone-menu"> - <li id="timezone-utc"><a data-timezone="UTC" href="#">UTC</a></li> - <li id="timezone-server" style="display: none;"><a data-timezone="{{ server_timezone }}" href="#">{{ server_timezone }}</a></li> - <li id="timezone-local"><a href="#">Local</a></li> - <li id="timezone-manual" style="display: none"><a data-timezone="" href="#"></a></li> - <li role="separator" class="divider"></li> - <li> - <form> - <label for="timezone-other">Other</label> - <input id="timezone-other" placeholder="Select Timezone name" autocomplete="off" tabindex="-1"> - </form> - </li> - </ul> - </li> - - {% if not current_user.is_anonymous %} - <li class="dropdown"> - <a class="dropdown-toggle" href="#"> - <span class="navbar-user-icon" title="{{g.user.get_full_name()}}"> - {% if current_user.first_name and current_user.last_name %} - <span>{{ (current_user.first_name[0] + current_user.last_name[0]).upper() }}</span> - {% else %} - <span class="material-icons">person</span> - {% endif %} - </span> - <b class="caret"></b> - </a> + {% if languages.keys()|length > 1 %} <ul class="dropdown-menu"> - <li><a href="{{appbuilder.get_url_for_userinfo}}"><span class="material-icons">account_circle</span>{{_("Your Profile")}}</a></li> - <li role="separator" class="divider"></li> - <li><a href="{{appbuilder.get_url_for_logout}}"><span class="material-icons">exit_to_app</span>{{_("Log Out")}}</a></li> + <li class="dropdown"> + {% for lang in languages %} + {% if lang != locale %} + <a href="{{appbuilder.get_url_for_locale(lang)}}"> + <div class="f16"><i class="flag {{languages[lang].get('flag')}}"></i> - {{languages[lang].get('name')}} + </div></a> + {% endif %} + {% endfor %} + </li> </ul> - </li> - {% else %} - <li> - <a href="{{appbuilder.get_url_for_login}}"><span class="material-icons">login</span>{{_("Log In")}}</a> - </li> + {% endif %} + </li> + {% endmacro %} + + {# clock and timezone menu #} + <li class="dropdown" id="timezone-dropdown"> + <a class="dropdown-toggle" style="display:none" href="#"> + <time id="clock" class="js-tooltip"></time> + <b class="caret"></b> + </a> + <ul class="dropdown-menu" id="timezone-menu"> + <li id="timezone-utc"><a data-timezone="UTC" href="#">UTC</a></li> + <li id="timezone-server" style="display: none;"><a data-timezone="{{ server_timezone }}" href="#">{{ server_timezone }}</a></li> + <li id="timezone-local"><a href="#">Local</a></li> + <li id="timezone-manual" style="display: none"><a data-timezone="" href="#"></a></li> + <li role="separator" class="divider"></li> <li> - <a href="../unity"><span class="material-icons">login</span>{{_("Log In via SSO")}}</a> + <form> + <label for="timezone-other">Other</label> + <input id="timezone-other" placeholder="Select Timezone name" autocomplete="off" tabindex="-1"> + </form> </li> - {% endif %} \ No newline at end of file + </ul> + </li> + + {% if auth_manager.is_logged_in() %} + <li class="dropdown"> + <a class="dropdown-toggle" href="#"> + <span class="navbar-user-icon" title="{{ auth_manager.get_user_name() }}"> + {% set user_name = auth_manager.get_user_name() %} + {% if user_name %} + {% set user_names = user_name.split(" ", 1) %} + <span>{% for name in user_names %}{{ name[0].upper() }}{% endfor %}</span> + {% else %} + <span class="material-icons">person</span> + {% endif %} + </span> + <b class="caret"></b> + </a> + <ul class="dropdown-menu"> + {% set user_profile_url = auth_manager.get_url_user_profile() %} + {% if user_profile_url %} + <li><a href="{{user_profile_url}}"><span class="material-icons">account_circle</span>{{_("Your Profile")}}</a></li> + <li role="separator" class="divider"></li> + {% endif %} + <li><a href="{{auth_manager.get_url_logout()}}"><span class="material-icons">exit_to_app</span>{{_("Log Out")}}</a></li> + </ul> + </li> + {% else %} + <li> + <a href="{{auth_manager.get_url_login()}}"><span class="material-icons">login</span>{{_("Log In")}}</a> + </li> + <li> + <a href="../unity"><span class="material-icons">login</span>{{_("Log In via SSO")}}</a> + </li> + {% endif %} \ No newline at end of file