Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extract auth to plugins, starting with ldap #3001

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 0 additions & 21 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@ GITHUB_TOKEN=
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=

## Login with LDAP
# AUTH_LDAP=true
# LDAP_TITLE= # eg. My LDAP Server}
# LDAP_HOST=192.168.25.188
# LDAP_PORT=389
# LDAP_BASE='dc=domain,dc=com'
# LDAP_UID=uid
# LDAP_BINDDN=userldap
# LDAP_PASSWORD=myldapsecret

## Login with Gitlab
# AUTH_GITLAB=true
# GITLAB_APPLICATION_ID=
Expand Down Expand Up @@ -227,17 +217,6 @@ PERIODICAL=stop_expired_deploys:60,remove_expired_locks:60,report_system_stats:6
## Only admins can (un)lock stages which affect production.
# PRODUCTION_STAGE_LOCK_REQUIRES_ADMIN=1

## Use LDAP_UID as user.external_id.
# The default is to use the Distinguished Name for users.external_id. If your organization changes
# any part of the DNs for any reason, this could cause any configured users to loose their current
# configuration since it will be assumed to be a new user with a new external_id. This feature
# forces the value of LDAP_UID (set above), which is used to query the user in the LDAP, which
# almost certainly is unique per user, to also be used for the external_id. Note, this name must
# also exist in the "extra" raw info:
# https://github.com/omniauth/omniauth-ldap/blob/master/README.md
# https://github.com/omniauth/omniauth-ldap/blob/master/lib/omniauth/strategies/ldap.rb#L17
# USE_LDAP_UID_AS_EXTERNAL_ID=1

## Plugin: Rollbar error reporting
# Report Samson's internal failures to Rollbar service
# ROLLBAR_ACCESS_TOKEN= # API token
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ gem 'omniauth'
gem 'omniauth-oauth2'
gem 'omniauth-github'
gem 'omniauth-google-oauth2'
gem 'omniauth-ldap'
gem 'omniauth-gitlab'
gem 'omniauth-bitbucket'
gem 'octokit'
Expand Down
8 changes: 7 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ PATH
samson_kubernetes (0.0.1)
kubeclient (>= 2)

PATH
remote: plugins/ldap
specs:
samson_ldap (0.0.1)
omniauth-ldap

PATH
remote: plugins/ledger
specs:
Expand Down Expand Up @@ -590,7 +596,6 @@ DEPENDENCIES
omniauth-github
omniauth-gitlab
omniauth-google-oauth2
omniauth-ldap
omniauth-oauth2
pagy
parallel
Expand Down Expand Up @@ -628,6 +633,7 @@ DEPENDENCIES
samson_jenkins!
samson_jenkins_status_checker!
samson_kubernetes!
samson_ldap!
samson_ledger!
samson_new_relic!
samson_pipelines!
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
27 changes: 3 additions & 24 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class SessionsController < ApplicationController
skip_before_action :login_user
skip_before_action :verify_authenticity_token, only: [:ldap]
skip_before_action :verify_authenticity_token, only: [:omniauth_callback]

def new
redirect_to root_path if current_user
Expand All @@ -14,22 +14,7 @@ def github
login(role_id: custom_role_or_default(role_id))
end

def google
return show_login_restriction unless allowed_to_login
login(role_id: custom_role_or_default(Role::VIEWER.id))
end

def ldap
return show_login_restriction unless allowed_to_login
login(role_id: custom_role_or_default(Role::VIEWER.id))
end

def gitlab
return show_login_restriction unless allowed_to_login
login(role_id: custom_role_or_default(Role::VIEWER.id))
end

def bitbucket
def omniauth_callback
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github is 1-off so keeping it separate for now, but eventually it should go through here too

return show_login_restriction unless allowed_to_login
login(role_id: custom_role_or_default(Role::VIEWER.id))
end
Expand Down Expand Up @@ -90,13 +75,7 @@ def redirect_to_origin_or_default
end

def login(options = {})
if auth_hash.provider == 'ldap' && ENV['AUTH_LDAP'] && ENV['USE_LDAP_UID_AS_EXTERNAL_ID']
uid_field = Rails.application.config.samson.ldap.uid
uid = auth_hash.extra.raw_info.send(uid_field).presence || raise
uid = Array(uid).first
else
uid = auth_hash.uid
end
uid = Samson::Hooks.fire(:omniauth_uid, auth_hash).compact.first || auth_hash.uid

user = find_or_create_user_from_hash(options.merge(
external_id: "#{strategy.name}-#{uid}",
Expand Down
14 changes: 9 additions & 5 deletions app/views/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
Please configure them via the AUTH_* environment variables as documented in
<%= link_to '.env.example', 'https://github.com/zendesk/samson/blob/master/.env.example' %>.
<% else %>
<% ['Github', 'Google', 'LDAP', 'Gitlab', 'Bitbucket'].each do |provider| %>
<% if Rails.application.config.samson.auth.public_send(provider.downcase) %>
<%= link_to omniauth_path(provider.downcase.to_sym), class: "action #{provider.downcase}" do %>
<%= image_tag image_url("#{provider.downcase}.png") %> Login with <%= provider %>
<% end %>
<%
providers = ['Github', 'Google', 'Gitlab', 'Bitbucket']
providers.select! { |p| Rails.application.config.samson.auth.public_send(p.downcase) }
providers.concat Samson::Hooks.fire(:omniauth_provider).compact
%>

<% providers.each do |provider| %>
<%= link_to omniauth_path(provider.downcase.to_sym), class: "action #{provider.downcase}" do %>
<%= image_tag image_url("auth/#{provider.downcase}.png") %> Login with <%= provider %>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could also be a plugin view, but this way the UI stays consistent ...

<% end %>
<% end %>
<% end %>
Expand Down
11 changes: 0 additions & 11 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,12 @@ class Application < Rails::Application
config.samson.github.web_url = deprecated_url.call("GITHUB_WEB_URL") || 'https://github.com'
config.samson.github.api_url = deprecated_url.call("GITHUB_API_URL") || 'https://api.github.com'

# Configuration for LDAP
config.samson.ldap = ActiveSupport::OrderedOptions.new
config.samson.ldap.title = ENV["LDAP_TITLE"].presence
config.samson.ldap.host = ENV["LDAP_HOST"].presence
config.samson.ldap.port = ENV["LDAP_PORT"].presence
config.samson.ldap.base = ENV["LDAP_BASE"].presence
config.samson.ldap.uid = ENV["LDAP_UID"].presence
config.samson.ldap.bind_dn = ENV["LDAP_BINDDN"].presence
config.samson.ldap.password = ENV["LDAP_PASSWORD"].presence

config.samson.gitlab = ActiveSupport::OrderedOptions.new
config.samson.gitlab.web_url = deprecated_url.call("GITLAB_URL") || 'https://gitlab.com'

config.samson.auth = ActiveSupport::OrderedOptions.new
config.samson.auth.github = Samson::EnvCheck.set?("AUTH_GITHUB")
config.samson.auth.google = Samson::EnvCheck.set?("AUTH_GOOGLE")
config.samson.auth.ldap = Samson::EnvCheck.set?("AUTH_LDAP")
config.samson.auth.gitlab = Samson::EnvCheck.set?("AUTH_GITLAB")
config.samson.auth.bitbucket = Samson::EnvCheck.set?("AUTH_BITBUCKET")

Expand Down
14 changes: 0 additions & 14 deletions config/initializers/omniauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@
}
end

if Rails.application.config.samson.auth.ldap
require 'omniauth-ldap'

provider OmniAuth::Strategies::LDAP,
title: Rails.application.config.samson.ldap.title,
host: Rails.application.config.samson.ldap.host,
port: Rails.application.config.samson.ldap.port,
method: 'plain',
base: Rails.application.config.samson.ldap.base,
uid: Rails.application.config.samson.ldap.uid,
bind_dn: Rails.application.config.samson.ldap.bind_dn,
password: Rails.application.config.samson.ldap.password
end

if Rails.application.config.samson.auth.bitbucket
require 'omniauth-bitbucket'
provider :bitbucket,
Expand Down
6 changes: 2 additions & 4 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,8 @@
get '/api/deploys', to: 'deploys#index'

get '/auth/github/callback', to: 'sessions#github'
get '/auth/google/callback', to: 'sessions#google'
post '/auth/ldap/callback', to: 'sessions#ldap'
get '/auth/gitlab/callback', to: 'sessions#gitlab'
get '/auth/bitbucket/callback', to: 'sessions#bitbucket'
get '/auth/:type/callback', to: 'sessions#omniauth_callback'
post '/auth/:type/callback', to: 'sessions#omniauth_callback'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any did not work and using match with a placeholder did not work either 🤷‍♂️

get '/auth/failure', to: 'sessions#failure'

get '/jobs/enabled', to: 'jobs#enabled', as: :enabled_jobs
Expand Down
1 change: 1 addition & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Available plugins:
- [Jenkins Status Checker](https://github.com/zendesk/samson/tree/master/plugins/jenkins_status_checker)
- [Hipchat notification](https://github.com/listia/samson_hipchat)
- [Kubernetes](https://github.com/zendesk/samson/tree/master/plugins/kubernetes)
- [LDAP](https://github.com/zendesk/samson/tree/master/plugins/ldap)
- [Ledger](https://github.com/zendesk/samson/tree/master/plugins/ledger)
- [Release Number From CI](https://github.com/redbubble/samson-release-number-from-ci)
- [NewRelic](https://github.com/zendesk/samson/tree/master/plugins/new_relic)
Expand Down
5 changes: 4 additions & 1 deletion lib/samson/hooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ class UserError < StandardError
:trace_method,
:trace_scope,
:asynchronous_performance_tracer,
:repo_provider_status
:repo_provider_status,
:omniauth_builder,
:omniauth_uid,
:omniauth_provider
].freeze

# Hooks that are slow and we want performance info on
Expand Down
27 changes: 27 additions & 0 deletions plugins/ldap/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Login with LDAP

```
AUTH_LDAP=true
LDAP_TITLE= # eg. My LDAP Server}
LDAP_HOST=192.168.25.188
LDAP_PORT=389
LDAP_BASE='dc=domain,dc=com'
LDAP_UID=uid
LDAP_BINDDN=userldap
LDAP_PASSWORD=myldapsecret
```

### Use LDAP_UID as user.external_id.

The default is to use the Distinguished Name for users.external_id. If your organization changes
any part of the DNs for any reason, this could cause any configured users to loose their current
configuration since it will be assumed to be a new user with a new external_id. This feature
forces the value of `LDAP_UID` (set above), which is used to query the user in the LDAP, which
almost certainly is unique per user, to also be used for the external_id. Note, this name must
also exist in the "extra" raw info:
https://github.com/omniauth/omniauth-ldap/blob/master/README.md
https://github.com/omniauth/omniauth-ldap/blob/master/lib/omniauth/strategies/ldap.rb#L17

```
USE_LDAP_UID_AS_EXTERNAL_ID=1
```
39 changes: 39 additions & 0 deletions plugins/ldap/lib/samson_ldap/samson_plugin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true
require 'omniauth-ldap'

module SamsonLdap
class Engine < Rails::Engine
end

def self.enabled?
Samson::EnvCheck.set?("AUTH_LDAP")
end
end

Rails.application.config.assets.precompile << "auth/ldap.png"

Samson::Hooks.callback :omniauth_builder do |builder|
if SamsonLdap.enabled?
builder.provider OmniAuth::Strategies::LDAP,
title: ENV["LDAP_TITLE"].presence,
host: ENV["LDAP_HOST"].presence,
port: ENV["LDAP_PORT"].presence,
method: 'plain',
base: ENV["LDAP_BASE"].presence,
uid: ENV["LDAP_UID"].presence,
bind_dn: ENV["LDAP_BINDDN"].presence,
password: ENV["LDAP_PASSWORD"].presence
end
end

Samson::Hooks.callback :omniauth_uid do |auth_hash|
if auth_hash.provider == 'ldap' && SamsonLdap.enabled? && ENV['USE_LDAP_UID_AS_EXTERNAL_ID']
uid_field = Rails.application.config.samson.ldap.uid
uid = auth_hash.extra.raw_info.send(uid_field).presence || raise
Array(uid).first
end
end

Samson::Hooks.callback :omniauth_provider do
'LDAP' if SamsonLdap.enabled?
end
8 changes: 8 additions & 0 deletions plugins/ldap/samson_ldap.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true
Gem::Specification.new 'samson_ldap', '0.0.1' do |s|
s.summary = 'ldap auth'
s.description = s.summary
s.authors = ['Michael Grosser']
s.email = 'mgrosser@zendesk.com'
s.add_runtime_dependency 'omniauth-ldap'
end