act as an saml identity provider

This commit is contained in:
Christophe Robillard 2020-11-12 16:09:21 +01:00
parent f30ac39ffb
commit 9347951cea
9 changed files with 93 additions and 0 deletions

View file

@ -65,6 +65,7 @@ gem 'rake-progressbar', require: false
gem 'react-rails'
gem 'rgeo-geojson'
gem 'rqrcode'
gem 'ruby-saml-idp'
gem 'sanitize-url'
gem 'sassc-rails' # Use SCSS for stylesheets
gem 'sentry-raven'

View file

@ -629,6 +629,7 @@ GEM
ruby-graphviz (1.2.5)
rexml
ruby-progressbar (1.10.1)
ruby-saml-idp (0.3.5)
ruby2_keywords (0.0.2)
ruby_parser (3.15.0)
sexp_processor (~> 4.9)
@ -860,6 +861,7 @@ DEPENDENCIES
rubocop-rails_config
rubocop-rspec-focused
ruby-debug-ide
ruby-saml-idp
sanitize-url
sassc-rails
scss_lint

View file

@ -0,0 +1,28 @@
class SamlIdpController < ActionController::Base
include SamlIdp::Controller
before_action :validate_saml_request
def new
if super_admin_signed_in?
@saml_response = encode_SAMLResponse(current_super_admin.email, saml_attributes)
render :template => "saml_idp/idp/saml_post", :layout => false
else
redirect_to root_path, alert: t("errors.messages.saml_not_authorized")
end
end
def metadata
render layout: false, content_type: "application/xml", formats: :xml
end
private
def saml_attributes
admin_attributes = %[<saml:AttributeStatement><saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"><saml:AttributeValue>#{current_super_admin.email}</saml:AttributeValue></saml:Attribute><saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml:AttributeValue>ds|#{current_super_admin.id}</saml:AttributeValue></saml:Attribute></saml:AttributeStatement>]
{
issuer_uri: saml_auth_url,
attributes_provider: admin_attributes
}
end
end

View file

@ -0,0 +1,21 @@
<EntityDescriptor entityID="urn:robids1.loca.lt" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate><%= SamlIdp.config.x509_certificate %></X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="<%= saml_auth_url %>"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="<%= saml_auth_url %>"/>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="E-Mail Address" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"/>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="Given Name" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"/>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="Name" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"/>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="Surname" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"/>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="Name ID" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"/>
</IDPSSODescriptor>
</EntityDescriptor>

View file

@ -20,6 +20,11 @@ SIGNING_KEY="aef3153a9829fa4ba10acb02927ac855df6b92795b1ad265d654443c4b14a017"
# Clé de chiffrement OTP, pour 2FA
OTP_SECRET_KEY=""
# Clé et certificat pour SAML IdP
# SAML_IDP_CERTIFICATE="billybop"
# SAML_IDP_SECRET_KEY="-----BEGIN RSA PRIVATE KEY-----\nblabla+blabla\n-----END RSA PRIVATE KEY-----\n"
# Database
DB_DATABASE="tps_development"
DB_HOST="localhost"

View file

@ -0,0 +1,7 @@
# The certificate and secret key are not fetched from secrets.yml because there is a problem to set a secret key from a multiline env var"
# So we fetch env var directly here
if Rails.env.production?
SamlIdp.config.x509_certificate = ENV.fetch("SAML_IDP_CERTIFICATE")
SamlIdp.config.secret_key = ENV.fetch("SAML_IDP_SECRET_KEY")
end

View file

@ -105,6 +105,7 @@ fr:
errors:
messages:
saml_not_authorized: "Vous n'êtes pas autorisé à accéder à ce service."
already_confirmed: "a déjà été validé(e), veuillez essayer de vous connecter"
confirmation_period_expired: "à confirmer dans les %{period}, merci de faire une nouvelle demande"
expired: "a expiré, merci den faire une nouvelle demande"

View file

@ -1,4 +1,8 @@
Rails.application.routes.draw do
get '/saml/auth' => 'saml_idp#new'
post '/saml/auth' => 'saml_idp#create'
get '/saml/metadata' => 'saml_idp#metadata'
#
# Manager
#

View file

@ -0,0 +1,24 @@
describe SamlIdpController do
describe '#new' do
let(:action) { get :new }
context 'without superadmin connected' do
it { expect(action).to redirect_to root_path }
it "display alert" do
action
expect(flash[:alert]).to eq("Vous n'êtes pas autorisé à accéder à ce service.")
end
end
context 'with superadmin connected' do
let(:superadmin) { create(:super_admin) }
before { sign_in superadmin }
it 'encode saml response' do
expect(subject).to receive(:encode_SAMLResponse).with(superadmin.email, anything())
action
end
end
end
end