├── config ├── routes.rb └── locales │ ├── zh.yml │ ├── ja.yml │ ├── en.yml │ └── de.yml ├── app ├── controllers │ └── env_auth_controller.rb └── views │ └── settings │ └── _redmine_env_auth_settings.html.erb ├── lang ├── zh.yml ├── ja.yml ├── en.yml └── de.yml ├── license ├── init.rb ├── readme.md └── lib └── redmine_env_auth └── env_auth_patch.rb /config/routes.rb: -------------------------------------------------------------------------------- 1 | RedmineApp::Application.routes.draw do 2 | get "env_auth/info", :to => "env_auth#info" 3 | get 'env_auth/logout', :to => "env_auth#logout" 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/env_auth_controller.rb: -------------------------------------------------------------------------------- 1 | class EnvAuthController < ApplicationController 2 | def info 3 | effective = remote_user 4 | variable_name = Setting.plugin_redmine_env_auth["env_variable_name"] 5 | original = request.env[variable_name] 6 | keys = request.env.keys.sort.select {|a| 7 | ["action_dispatch.", "action_controller.", "rack.", "puma."].none? {|b| a.start_with?(b)} 8 | }.join("\n ") 9 | text = [ 10 | "variable name: #{variable_name}", 11 | "original value: #{original.inspect}", 12 | "effective value: #{effective.inspect}" 13 | ].join("\n") 14 | 15 | text = "#{text}\navailable variables:\n #{keys}" 16 | render :plain => text 17 | end 18 | 19 | def logout 20 | if Setting.plugin_redmine_env_auth["external_logout_target"] == "" 21 | redirect_to signout_path 22 | else 23 | redirect_to Setting.plugin_redmine_env_auth["external_logout_target"] 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lang/zh.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | label_allow_other_login_admins: 所有管理员 3 | label_allow_other_login_all: 所有用户 4 | label_allow_other_login: 允许标准登录 5 | label_allow_other_login_none: 已禁用 6 | label_allow_other_login_users: 一些用户(以逗号分隔) 7 | label_default: 默认 8 | label_email_address: 电子邮件地址 9 | label_enabled: 启用 10 | label_env_variable_name: 请求环境变量的名称 11 | label_ldap_checked_auto_registration: 带有LDAP检查的自动注册 12 | label_login_name: 登录名 13 | label_remove_suffix_help: 将从环境变量文本的末尾移除给定的文本 14 | label_remove_suffix: 移除后缀 15 | label_redmine_user_property: Redmine用户属性 16 | label_env_checked_auto_registration: 使用环境变量的自动注册 17 | label_env_variable_firstname: 名字的变量 18 | label_env_variable_lastname: 姓氏的变量 19 | label_env_variable_email: 邮箱的变量 20 | label_env_variable_admins: 管理员登录列表 21 | label_env_variable_admins_description: 以逗号分隔的登录列表,这些登录将被注册为管理员 22 | label_env_variable_new_user_initial_locked: 锁定新注册的账户 23 | label_show_logout_link: 显示登出链接 24 | label_external_logout_target: 登出时重定向的位置 25 | label_external_logout_target_description: 指定一个外部登出服务。如果为空,将使用内部登出路径 -------------------------------------------------------------------------------- /config/locales/zh.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | label_allow_other_login_admins: 所有管理员 3 | label_allow_other_login_all: 所有用户 4 | label_allow_other_login: 允许标准登录 5 | label_allow_other_login_none: 已禁用 6 | label_allow_other_login_users: 一些用户(以逗号分隔) 7 | label_default: 默认 8 | label_email_address: 电子邮件地址 9 | label_enabled: 启用 10 | label_env_variable_name: 请求环境变量的名称 11 | label_ldap_checked_auto_registration: 带有LDAP检查的自动注册 12 | label_login_name: 登录名 13 | label_remove_suffix_help: 将从环境变量文本的末尾移除给定的文本 14 | label_remove_suffix: 移除后缀 15 | label_redmine_user_property: Redmine用户属性 16 | label_env_checked_auto_registration: 使用环境变量的自动注册 17 | label_env_variable_firstname: 名字的变量 18 | label_env_variable_lastname: 姓氏的变量 19 | label_env_variable_email: 邮箱的变量 20 | label_env_variable_admins: 管理员登录列表 21 | label_env_variable_admins_description: 以逗号分隔的登录列表,这些登录将被注册为管理员 22 | label_env_variable_new_user_initial_locked: 锁定新注册的账户 23 | label_show_logout_link: 显示登出链接 24 | label_external_logout_target: 登出时重定向的位置 25 | label_external_logout_target_description: 指定一个外部登出服务。如果为空,将使用内部登出路径 -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Adam Lantos 2 | Copyright (c) 2018 Intera GmbH 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /lang/ja.yml: -------------------------------------------------------------------------------- 1 | # Japanese translation by Akiko Takano, tohosaku 2 | ja: 3 | label_allow_other_login_admins: 全てのシステム管理者 4 | label_allow_other_login_all: 全てのユーザー 5 | label_allow_other_login: 通常のログインを許可 6 | label_allow_other_login_none: 許可しない 7 | label_allow_other_login_users: 指定されたユーザーのみ (カンマ区切り) 8 | label_default: デフォルト 9 | label_email_address: メールアドレス 10 | label_enabled: 有効にする 11 | label_env_variable_name: サーバの環境変数名 12 | label_ldap_checked_auto_registration: LDAPの確認に基づく自動登録 13 | label_login_name: ログイン名 14 | label_remove_suffix_help: 入力された文字列は、環境変数の末尾から削除されます。 15 | label_remove_suffix: 削除するサフィックス 16 | label_redmine_user_property: 対応するredmine 側のユーザー情報 17 | label_env_checked_auto_registration: 環境変数による自動登録 18 | label_env_variable_firstname: 名の変数 19 | label_env_variable_lastname: 姓の変数 20 | label_env_variable_email: メールの変数 21 | label_env_variable_admins: 管理者ログインのリスト 22 | label_env_variable_admins_description: 管理者として登録されるログインのカンマ区切りリスト 23 | label_env_variable_new_user_initial_locked: 新規登録アカウントをロック 24 | label_show_logout_link: ログアウトリンクを表示 25 | label_external_logout_target: ログアウト時のリダイレクト先 26 | label_external_logout_target_description: 外部ログアウトサービスを指定します。空の場合、内部のログアウトパスが使用されます。 -------------------------------------------------------------------------------- /config/locales/ja.yml: -------------------------------------------------------------------------------- 1 | # Japanese translation by Akiko Takano, tohosaku 2 | ja: 3 | label_allow_other_login_admins: 全てのシステム管理者 4 | label_allow_other_login_all: 全てのユーザー 5 | label_allow_other_login: 通常のログインを許可 6 | label_allow_other_login_none: 許可しない 7 | label_allow_other_login_users: 指定されたユーザーのみ (カンマ区切り) 8 | label_default: デフォルト 9 | label_email_address: メールアドレス 10 | label_enabled: 有効にする 11 | label_env_variable_name: サーバの環境変数名 12 | label_ldap_checked_auto_registration: LDAPの確認に基づく自動登録 13 | label_login_name: ログイン名 14 | label_remove_suffix_help: 入力された文字列は、環境変数の末尾から削除されます。 15 | label_remove_suffix: 削除するサフィックス 16 | label_redmine_user_property: 対応するredmine 側のユーザー情報 17 | label_env_checked_auto_registration: 環境変数による自動登録 18 | label_env_variable_firstname: 名の変数 19 | label_env_variable_lastname: 姓の変数 20 | label_env_variable_email: メールの変数 21 | label_env_variable_admins: 管理者ログインのリスト 22 | label_env_variable_admins_description: 管理者として登録されるログインのカンマ区切りリスト 23 | label_env_variable_new_user_initial_locked: 新規登録アカウントをロック 24 | label_show_logout_link: ログアウトリンクを表示 25 | label_external_logout_target: ログアウト時のリダイレクト先 26 | label_external_logout_target_description: 外部ログアウトサービスを指定します。空の場合、内部のログアウトパスが使用されます。 -------------------------------------------------------------------------------- /lang/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | label_allow_other_login_admins: all admininstrators 3 | label_allow_other_login_all: all users 4 | label_allow_other_login: allow standard login 5 | label_allow_other_login_none: disabled 6 | label_allow_other_login_users: some users (comma separated) 7 | label_default: default 8 | label_email_address: email address 9 | label_enabled: enable 10 | label_env_variable_name: name of request environment variable 11 | label_ldap_checked_auto_registration: automatic registration with ldap check 12 | label_login_name: login name 13 | label_remove_suffix_help: the given text will be removed from the end of the text in the environment variable 14 | label_remove_suffix: remove suffix 15 | label_redmine_user_property: redmine user property 16 | label_env_checked_auto_registration: automatic registration with env variables 17 | label_env_variable_firstname: variable with firstname 18 | label_env_variable_lastname: variable with lastname 19 | label_env_variable_email: variable with email 20 | label_env_variable_admins: list of admin logins 21 | label_env_variable_admins_description: comma separated list of login that will be registered as admins 22 | label_env_variable_new_user_initial_locked: lock newly registered accounts 23 | label_show_logout_link: display logout link 24 | label_external_logout_target: where to redirect on logout 25 | label_external_logout_target_description: specify an external logout service. if empty the internal logout path is used -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | label_allow_other_login_admins: all admininstrators 3 | label_allow_other_login_all: all users 4 | label_allow_other_login: allow standard login 5 | label_allow_other_login_none: disabled 6 | label_allow_other_login_users: some users (comma separated) 7 | label_default: default 8 | label_email_address: email address 9 | label_enabled: enable 10 | label_env_variable_name: name of request environment variable 11 | label_ldap_checked_auto_registration: automatic registration with ldap check 12 | label_login_name: login name 13 | label_remove_suffix_help: the given text will be removed from the end of the text in the environment variable 14 | label_remove_suffix: remove suffix 15 | label_redmine_user_property: redmine user property 16 | label_env_checked_auto_registration: automatic registration with env variables 17 | label_env_variable_firstname: variable with firstname 18 | label_env_variable_lastname: variable with lastname 19 | label_env_variable_email: variable with email 20 | label_env_variable_admins: list of admin logins 21 | label_env_variable_admins_description: comma separated list of login that will be registered as admins 22 | label_env_variable_new_user_initial_locked: lock newly registered accounts 23 | label_show_logout_link: display logout link 24 | label_external_logout_target: where to redirect on logout 25 | label_external_logout_target_description: specify an external logout service. if empty the internal logout path is used -------------------------------------------------------------------------------- /lang/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | label_allow_other_login_admins: Für Administratoren 3 | label_allow_other_login_all: Für alle Benutzer 4 | label_allow_other_login_none: Deaktiviert 5 | label_allow_other_login: Standardlogin erlauben 6 | label_allow_other_login_users: Für bestimmte Benutzer (Kommagetrennt) 7 | label_default: Vorgabe 8 | label_email_address: E-Mail-Adresse 9 | label_enabled: Plugin verwenden 10 | label_env_variable_name: Name der Umgebungsvariable für die Benutzerdaten 11 | label_ldap_checked_auto_registration: Automatische Registrierung mit LDAP-Abgleich 12 | label_login_name: Loginname 13 | label_remove_suffix_help: Der eingetragene Text wird vom Ende des Texts in der Umgebungsvariable abgeschnitten 14 | label_remove_suffix: Entferne suffix 15 | label_redmine_user_property: Redmine Benutzereigenschaft 16 | label_env_checked_auto_registration: Auto-Registrierung mit Umgebungsvariablen 17 | label_env_variable_firstname: Variable mit Vorname 18 | label_env_variable_lastname: Variable mit Nachname 19 | label_env_variable_email: Variable mit Email-Adresse 20 | label_env_variable_admins: Liste mit Admin-Logins 21 | label_env_variable_admins_description: Kommaseparierte Liste mit Logins, die als Administratoren registriert werden 22 | label_env_variable_new_user_initial_locked: Sperre neu registrierte Konten 23 | label_show_logout_link: Abmelden-Link anzeigen 24 | label_external_logout_target: Ziel für Abmelden-Link 25 | label_external_logout_target_description: hier kann ein externer Abmeldeservice angegeben werden. Wenn leer, Umleitung auf internen logout-Pfad -------------------------------------------------------------------------------- /config/locales/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | label_allow_other_login_admins: Für Administratoren 3 | label_allow_other_login_all: Für alle Benutzer 4 | label_allow_other_login_none: Deaktiviert 5 | label_allow_other_login: Standardlogin erlauben 6 | label_allow_other_login_users: Für bestimmte Benutzer (Kommagetrennt) 7 | label_default: Vorgabe 8 | label_email_address: E-Mail-Adresse 9 | label_enabled: Plugin verwenden 10 | label_env_variable_name: Name der Umgebungsvariable für die Benutzerdaten 11 | label_ldap_checked_auto_registration: Automatische Registrierung mit LDAP-Abgleich 12 | label_login_name: Loginname 13 | label_remove_suffix_help: Der eingetragene Text wird vom Ende des Texts in der Umgebungsvariable abgeschnitten 14 | label_remove_suffix: Entferne suffix 15 | label_redmine_user_property: Redmine Benutzereigenschaft 16 | label_env_checked_auto_registration: Auto-Registrierung mit Umgebungsvariablen 17 | label_env_variable_firstname: Variable mit Vorname 18 | label_env_variable_lastname: Variable mit Nachname 19 | label_env_variable_email: Variable mit Email-Adresse 20 | label_env_variable_admins: Liste mit Admin-Logins 21 | label_env_variable_admins_description: Kommaseparierte Liste mit Logins, die als Administratoren registriert werden 22 | label_env_variable_new_user_initial_locked: Sperre neu registrierte Konten 23 | label_show_logout_link: Abmelden-Link anzeigen 24 | label_external_logout_target: Ziel für Abmelden-Link 25 | label_external_logout_target_description: hier kann ein externer Abmeldeservice angegeben werden. Wenn leer, Umleitung auf internen logout-Pfad -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | Redmine::Plugin.register :redmine_env_auth do 2 | name "Request Environment Authentication" 3 | author "Intera GmbH" 4 | url "http://github.com/intera/redmine_env_auth" if respond_to?(:url) 5 | description "A plugin for authentication based on variables in the request environment." 6 | version "1.3" 7 | 8 | Redmine::MenuManager.map :account_menu do |menu| 9 | # hide the logout link if an automatic login is active 10 | menu.delete :logout 11 | menu.push :logout, {:controller => 'env_auth', :action => 'logout'}, :caption => :label_logout, :if => Proc.new { 12 | if !User.current.logged? 13 | false 14 | elsif Setting.plugin_redmine_env_auth["enabled"] != "true" 15 | true 16 | elsif Setting.plugin_redmine_env_auth["show_logout_link"] == "true" 17 | true 18 | else 19 | false 20 | end 21 | }, :after => :my_account 22 | end 23 | 24 | settings :partial => "settings/redmine_env_auth_settings", 25 | :default => { 26 | "allow_other_login" => "admins", 27 | "allow_other_login_users" => "", 28 | "enabled" => "false", 29 | "env_variable_name" => "REMOTE_USER", 30 | "ldap_checked_auto_registration" => "false", 31 | "redmine_user_property" => "login", 32 | "remove_suffix" => "", 33 | "env_checked_auto_registration" => "false", 34 | "env_variable_firstname" => "GIVENNAME", 35 | "env_variable_lastname" => "LASTNAME", 36 | "env_variable_email" => "EMAIL", 37 | "env_variable_admins" => "", 38 | "env_variable_new_user_initial_locked" => "false", 39 | "show_logout_link" => "false", 40 | "external_logout_target" => "" 41 | } 42 | end 43 | 44 | if Rails.version > '6.0' && Rails.autoloaders.zeitwerk_enabled? 45 | RedmineEnvAuth::EnvAuthPatch.install 46 | else 47 | Rails.configuration.to_prepare do 48 | RedmineEnvAuth::EnvAuthPatch.install 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /app/views/settings/_redmine_env_auth_settings.html.erb: -------------------------------------------------------------------------------- 1 |

2 | <%= content_tag(:label, l(:label_enabled))%> 3 | <%= check_box_tag "settings[enabled]", true, @settings["enabled"] == "true" %> 4 |

5 | 6 |

7 | <%= content_tag(:label, l(:label_env_variable_name)) %> 8 | <%= text_field_tag "settings[env_variable_name]", @settings["env_variable_name"] %>
9 | <%= l(:label_default)%>: REMOTE_USER 10 |

11 | 12 |

13 | <%= content_tag(:label, l(:label_remove_suffix)) %> 14 | <%= text_field_tag "settings[remove_suffix]", @settings["remove_suffix"] %>
15 | <%= l(:label_remove_suffix_help)%> 16 |

17 | 18 |

19 | <%= content_tag(:label, l(:label_redmine_user_property))%> 20 | <%= radio_button_tag "settings[redmine_user_property]", "login", @settings["redmine_user_property"] == "login" %> 21 | <%= l(:label_login_name)%>
22 | <%= radio_button_tag "settings[redmine_user_property]", "mail", @settings["redmine_user_property"] == "mail" %> 23 | <%= l(:label_email_address)%> 24 |

25 | 26 |

27 | <%= content_tag(:label, l(:label_allow_other_login))%> 28 | <%= radio_button_tag "settings[allow_other_login]", "admins", @settings["allow_other_login"] == "admins" %> 29 | <%= l(:label_allow_other_login_admins)%>
30 | <%= radio_button_tag "settings[allow_other_login]", "all", @settings["allow_other_login"] == "all" %> 31 | <%= l(:label_allow_other_login_all)%>
32 | <%= radio_button_tag "settings[allow_other_login]", "users", @settings["allow_other_login"] == "users" %> 33 | <%= l(:label_allow_other_login_users)%>
34 | <%= text_field_tag "settings[allow_other_login_users]", @settings["allow_other_login_users"] %>
35 | <%= radio_button_tag "settings[allow_other_login]", "none", @settings["allow_other_login"] == "none" %> 36 | <%= l(:label_allow_other_login_none)%>
37 |

38 | 39 |

40 | <%= content_tag(:label, l(:label_ldap_checked_auto_registration))%> 41 | <%= check_box_tag "settings[ldap_checked_auto_registration]", true, @settings["ldap_checked_auto_registration"] == "true" %> 42 |

43 | 44 |

45 | <%= content_tag(:label, l(:label_env_checked_auto_registration))%> 46 | <%= check_box_tag "settings[env_checked_auto_registration]", true, @settings["env_checked_auto_registration"] == "true" %>
47 | <%= content_tag(:label, l(:label_env_variable_firstname)) %> 48 | <%= text_field_tag "settings[env_variable_firstname]", @settings["env_variable_firstname"] %>
49 | <%= l(:label_default)%>: GIVENNAME
50 | <%= content_tag(:label, l(:label_env_variable_lastname)) %> 51 | <%= text_field_tag "settings[env_variable_lastname]", @settings["env_variable_lastname"] %>
52 | <%= l(:label_default)%>: LASTNAME
53 | <%= content_tag(:label, l(:label_env_variable_email)) %> 54 | <%= text_field_tag "settings[env_variable_email]", @settings["env_variable_email"] %>
55 | <%= l(:label_default)%>: EMAIL
56 | <%= content_tag(:label, l(:label_env_variable_admins)) %> 57 | <%= text_field_tag "settings[env_variable_admins]", @settings["env_variable_admins"] %>
58 | <%= l(:label_env_variable_admins_description)%>
59 | <%= content_tag(:label, l(:label_env_variable_new_user_initial_locked))%> 60 | <%= check_box_tag "settings[env_variable_new_user_initial_locked]", true, @settings["env_variable_new_user_initial_locked"] == "true" %>
61 | <%= content_tag(:label, l(:label_show_logout_link))%> 62 | <%= check_box_tag "settings[show_logout_link]", true, @settings["show_logout_link"] == "true" %>
63 | <%= content_tag(:label, l(:label_external_logout_target)) %> 64 | <%= text_field_tag "settings[external_logout_target]", @settings["external_logout_target"] %>
65 | <%= l(:label_external_logout_target_description)%>
66 |

67 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # redmine_env_auth 2 | this plugin allows to authenticate users using a variable in the request environment (set by the server or proxy server, in rails "request.env"). this variable can be custom named. one use case is log-in with single sign-on solutions (SSO) like ntlm/kerberos where the server (for example apache with mod_auth_kerberos) sets the request environment variable $REMOTE_USER to a username when a user has been authenticated. 3 | 4 | # features 5 | * automatically log-in users if a specific request environment variable is set, and log-out if it is unset 6 | * option to allow conventional redmine logins for admins, specific users or everyone 7 | * option to register users automatically if they are found using ldap 8 | * option to register users automatically from additional environment variables 9 | * "sign out" link hidden when autologin is active 10 | * compatible with redmine 4 11 | 12 | # installation 13 | ## download 14 | dowload a [release](https://github.com/Intera/redmine_env_auth/tags) or a [zip file](https://github.com/Intera/redmine_env_auth/archive/master.zip) via github and unpack the archive. 15 | alternatively you can clone the repository with "git clone https://github.com/Intera/redmine_env_auth.git" 16 | 17 | ## setup 18 | move the "redmine_env_auth" directory from the download to your redmine installation directory under "plugins/", so that you have "plugins/redmine_env_auth". restart redmine. if the file system permissions are right, the plugin should now be installed. go into redmine under "Administration" "Plugins" to check that it is listed and eventually use the configure link to adjust settings of the plugin 19 | 20 | # settings 21 | |name|default|description| 22 | |----|-------|-----------| 23 | |enabled|true|enable or disable the plugin| 24 | |name of request environment variable|REMOTE_USER|| 25 | |remove suffix||the given text will be removed from the end of the text in the environment variable| 26 | |redmine user property|login|match local redmine users by login name or alternatively email address| 27 | |allow other login|admins|this allows conventional logins. users must be allowed to see the login form| 28 | |automatic registration with ldap check|false|if a matching local redmine user can not be found, try to find it in ldap and, if found, automatically create the user in redmine. the user will be linked with the ldap as the authentication source| 29 | 30 | ## redmine behind proxy 31 | if redmine is run with a separate http server and another server first receives and proxies incoming requests, then the cgi environment will not be available to redmine and the authentication variable will not be set. this is the case for example if redmine is run with puma and another server like nginx or apache forwards requests to it. in this case, a http header can be used to transmit the user information. the setting for the env auth variable name must correspond to the header name used. with puma a HTTP_ prefix is added, with the following example config the variable name would be ``HTTP_X_REMOTE_USER`` instead of the default ``REMOTE_USER``. 32 | 33 | important for security: under no circumstances should this header be forwarded from the client. you need to make sure that it is overwritten with your authentication value or removed if it exists before sending it to the redmine server. 34 | 35 | apache 2.4 config example: 36 | ``` 37 | RequestHeader unset X_REMOTE_USER 38 | RewriteEngine On 39 | RewriteCond %{LA-U:REMOTE_USER} (.+) 40 | RewriteRule .* - [E=RU:%1] 41 | RequestHeader add X_REMOTE_USER %{RU}e 42 | ``` 43 | 44 | X_REMOTE_USER is first unset to ensure that it isnt set by some other source like a client or another proxy. the rewrite engine is used to look ahead (wait) on a future state of the variable (after it has been set by the authentication module, LA-U), 45 | and when it is set (RewriteCond) apply the RewriteRule that doesnt rewrite the url but sets an environment variable RU with the match from the condition. 46 | this requires the apache modules "headers" and "rewrite". 47 | 48 | this other example can be found online, but it doesnt seem to work: 49 | ``` 50 | RequestHeader unset X_REMOTE_USER 51 | RequestHeader set X_REMOTE_USER expr=%{REMOTE_USER} 52 | ``` 53 | 54 | # debugging 55 | * /env_auth/info displays the current name and value of the environment variable that is configured to be used 56 | * messages with the debug levels debug, info and error are written into the redmine log {redmine_root}/log/{environment}.log. log levels are set in `{redmine_root}/config/additional_environment.rb` (might have to be created), for example with the line `config.log_level = :debug`. 57 | * you can display log output as it is being written with `tail -f production.log | grep redmine_env_auth` 58 | * redmine sessions can be ended by going to /logout and clicking on the button 59 | 60 | if you are locked out because the allow other login setting is not set to "all" and the request environment variable isnt set correctly, you might want to reset the plugin settings to be able to log-in with the conventional redmine login. the plugin settings are stored in the database and the sql to delete them is ``delete from settings where name="plugin_redmine_env_auth";``. you might have to restart redmine afterwards 61 | 62 | # environment auto registration 63 | users can also be registered based on environment variables, with options for initial account locking, admin assignment, and custom logout services. 64 | 65 | ## settings 66 | * enable 67 | * environment variable name for the first name 68 | * environment variable name for the last name 69 | * environment variable name for the email 70 | * comma-separated list of admin logins 71 | * lock newly registered accounts 72 | * display a logout link 73 | * url for an external logout service 74 | 75 | # possible enhancements 76 | * document how passing the login variable to only specific url paths can work 77 | * automated tests 78 | 79 | # changelog 80 | * 2024-11-21: quick test with redmine 6 81 | * 2018-08: completely revised, less code, added debugging features 82 | 83 | # copyright and license 84 | originally based on code from adam lantos, [redmine_http_auth](https://github.com/AdamLantos/redmine_http_auth). 85 | * copyright (c) 2010 niif institute and adam lantos, released under the mit license 86 | * copyright (c) 2018 [intera](https://www.intera.de/) (mit license) 87 | -------------------------------------------------------------------------------- /lib/redmine_env_auth/env_auth_patch.rb: -------------------------------------------------------------------------------- 1 | module RedmineEnvAuth 2 | module EnvAuthPatch 3 | 4 | module PrependMethods 5 | def find_current_user 6 | find_current_user_with_envauth 7 | super 8 | end 9 | end 10 | 11 | def self.install 12 | ApplicationController.class_eval do 13 | def remote_user 14 | #request.env["HTTP_X_REMOTE_USER"] = "" 15 | key = request.env[Setting.plugin_redmine_env_auth["env_variable_name"]] 16 | return nil unless key 17 | suffix = Setting.plugin_redmine_env_auth["remove_suffix"] 18 | if suffix.is_a?(String) and not suffix.empty? 19 | key.chomp suffix 20 | else 21 | key 22 | end 23 | end 24 | 25 | def get_env_firstname 26 | request.env[Setting.plugin_redmine_env_auth["env_variable_firstname"]] 27 | end 28 | 29 | def get_env_lastname 30 | request.env[Setting.plugin_redmine_env_auth["env_variable_lastname"]] 31 | end 32 | 33 | def get_env_mail 34 | request.env[Setting.plugin_redmine_env_auth["env_variable_email"]] 35 | end 36 | 37 | def allow_other_login? user 38 | # User -> boolean 39 | # this checks if an existing session is allowed. redmine sessions can currently also 40 | # be started using the standard sign-in form. 41 | allow_other_login = Setting.plugin_redmine_env_auth["allow_other_login"] 42 | if not ["admins", "users", "all", "none"].include? allow_other_login 43 | allow_other_login = "all" 44 | end 45 | allow_other_login = false if "none" == allow_other_login 46 | if "users" == allow_other_login 47 | allow_other_login_users = Setting.plugin_redmine_env_auth["allow_other_login_users"] 48 | allow_other_login_users = allow_other_login_users.split(",").map {|a| a.strip } 49 | end 50 | if allow_other_login 51 | return true if ("all" == allow_other_login) 52 | return true if ("admins" == allow_other_login) and user.admin? 53 | return true if ("users" == allow_other_login) and allow_other_login_users.include?(user.login) 54 | end 55 | false 56 | end 57 | 58 | def find_current_user_with_envauth 59 | plugin_disabled = Setting.plugin_redmine_env_auth["enabled"] != "true" 60 | if plugin_disabled then return find_current_user_without_envauth end 61 | user = find_current_user_without_envauth 62 | if user and allow_other_login? user then 63 | if "login" == request.env["action_controller.instance"].action_name 64 | logger.debug "redmine_env_auth: ignoring active session and showing login form" 65 | reset_session 66 | return nil 67 | else 68 | logger.debug "redmine_env_auth: continuing active session for #{user.login}" 69 | return user 70 | end 71 | end 72 | logger.debug "redmine_env_auth: trying to log in using environment variable" 73 | key = remote_user 74 | if !key or key.empty? 75 | logger.info "redmine_env_auth: environment variable is unset. logging out any existing users. only allowed users can use standard login" 76 | reset_session if user 77 | return nil 78 | end 79 | logger.debug "redmine_env_auth: environment variable value is \"#{key}\"" 80 | property = Setting.plugin_redmine_env_auth["redmine_user_property"] 81 | if user 82 | # existing session, check if user property matches current value of environment variable 83 | reuse_session = false 84 | if "mail" == property 85 | reuse_session = key == user.mail 86 | else 87 | reuse_session = key == user.login 88 | end 89 | if reuse_session 90 | logger.debug "redmine_env_auth: continuing active session for \"#{user.login}\"" 91 | return user 92 | end 93 | reset_session 94 | end 95 | # try redmine users 96 | if "mail" == property 97 | user = User.find_by_mail key 98 | else 99 | user = User.find_by_login key 100 | end 101 | 102 | # try ldap users and auto registration 103 | if not user 104 | auto = "true" == Setting.plugin_redmine_env_auth["ldap_checked_auto_registration"] 105 | if auto then user = register_if_exists_in_ldap key end 106 | end 107 | if not user 108 | auto = "true" == Setting.plugin_redmine_env_auth["env_checked_auto_registration"] 109 | if auto then user = register_if_env_auto_registration_checked key end 110 | end 111 | 112 | if user and user.is_a? User and user.locked? 113 | logger.debug "user is locked. login is not allowed" 114 | reset_session 115 | nil 116 | end 117 | 118 | # start session or return nil 119 | if user and user.is_a? User 120 | logger.debug "redmine_env_auth: user found, start session" 121 | start_user_session user 122 | user.update_attribute :last_login_on, Time.now 123 | User.current = user 124 | else 125 | logger.debug "redmine_env_auth: redmine user #{key} not found using property #{property}" 126 | nil 127 | end 128 | end 129 | 130 | def register_if_exists_in_ldap login 131 | # search all ldap sources for a user with the given name and if found, 132 | # create a user with that name in redmine. 133 | auth_sources = AuthSource.where :type => "AuthSourceLdap" 134 | if 0 == auth_sources.count 135 | logger.debug "redmine_env_auth: no ldap source found" 136 | return 137 | end 138 | # attributes that redmine requires for creating a user 139 | required_attrs = [:firstname, :lastname, :mail] 140 | auth_sources.find do |auth_source| 141 | users = auth_source.search login 142 | next if 0 == users.length 143 | ldap_user = users.first 144 | next if login != ldap_user[:login] 145 | missing_attrs = required_attrs - ldap_user.keys 146 | if 0 < missing_attrs.length 147 | logger.debug "redmine_env_auth: missing attributes #{missing_attrs} from ldap, cant create user" 148 | next 149 | end 150 | user = User.new ldap_user.slice(:firstname, :lastname, :mail) 151 | user.login = ldap_user[:login] 152 | # this allows newly registered users to log in using ldap if redmine_env_auth is disabled 153 | user.auth_source_id = auth_source.id 154 | if user.save 155 | user.reload 156 | logger.debug "redmine_env_auth: user creation after ldap sync successful" 157 | return user 158 | else 159 | logger.error "redmine_env_auth: user creation after ldap sync failed" 160 | return 161 | end 162 | end 163 | logger.debug "redmine_env_auth: no user found via ldap" 164 | nil 165 | end 166 | 167 | def register_if_env_auto_registration_checked login 168 | logger.debug "attempt to create env-user" 169 | # check if required fields exist 170 | if get_env_lastname.blank? 171 | logger.debug "redmine_env_auth: lastname is empty. cannot create user" 172 | return nil 173 | end 174 | 175 | if get_env_firstname.blank? 176 | logger.debug "redmine_env_auth: firstname is empty. cannot create user" 177 | return nil 178 | end 179 | 180 | if get_env_mail.blank? 181 | logger.debug "redmine_env_auth: email is empty. cannot create user" 182 | return nil 183 | end 184 | 185 | user = User.new(:firstname => get_env_firstname, :lastname => get_env_lastname, :mail => get_env_mail) 186 | user.login = login 187 | 188 | if Setting.plugin_redmine_env_auth["env_variable_new_user_initial_locked"] == "true" 189 | user.lock! 190 | end 191 | 192 | if Setting.plugin_redmine_env_auth["env_variable_admins"].split(/\s*,\s*/).include? login 193 | user.admin = true 194 | end 195 | 196 | if user.save 197 | user.reload 198 | logger.debug "redmine_env_auth: user creation successful" 199 | return user 200 | else 201 | logger.error "redmine_env_auth: user creation failed - #{user.errors.full_messages.join(', ')}" 202 | return nil 203 | end 204 | end 205 | 206 | if self.respond_to?(:alias_method_chain) # Rails < 5 207 | # register find_current_user_with/without_envauth 208 | alias_method_chain :find_current_user, :envauth 209 | else # Rails >= 5 210 | alias_method :find_current_user_without_envauth, :find_current_user 211 | prepend PrependMethods 212 | end 213 | end 214 | end 215 | end 216 | end 217 | --------------------------------------------------------------------------------