Skip to content

Commit

Permalink
Merge pull request #87 from jbfavre/add_ldap_support
Browse files Browse the repository at this point in the history
Add ldap support
  • Loading branch information
JonathanTron committed Oct 2, 2015
2 parents 9abc43e + f96bb8c commit 5d1de96
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 10 deletions.
10 changes: 10 additions & 0 deletions attributes/default.rb
Expand Up @@ -79,6 +79,16 @@
value: 'grafana.db'
}

default['grafana']['ini']['auth.ldap']['enabled'] = {
comment: '',
disable: true,
value: false
}
default['grafana']['ini']['auth.ldap']['config_file'] = {
disable: true,
value: '/etc/grafana/ldap.toml'
}

# server
default['grafana']['ini']['server']['protocol'] = 'http'
default['grafana']['ini']['server']['http_port'] = 3000
Expand Down
89 changes: 89 additions & 0 deletions attributes/ldap_config.rb
@@ -0,0 +1,89 @@
default['grafana']['ldap_verbose_logging'] = false

default['grafana']['ldap']['[servers]']['host'] = {
comment: 'Ldap server host',
disable: false,
value: '"127.0.0.1"'
}
default['grafana']['ldap']['[servers]']['port'] = {
comment: 'Default port is 389 or 636 if use_ssl = true',
disable: false,
value: 389
}
default['grafana']['ldap']['[servers]']['use_ssl'] = {
comment: 'Set to true if ldap server supports TLS',
disable: false,
value: false
}
default['grafana']['ldap']['[servers]']['ssl_skip_verify'] = {
comment: 'set to true if you want to skip ssl cert validation',
disable: false,
value: false
}
default['grafana']['ldap']['[servers]']['bind_dn'] = {
comment: 'Search user bind dn',
disable: false,
value: '"cn=admin,dc=grafana,dc=org"'
}
default['grafana']['ldap']['[servers]']['bind_password'] = {
comment: 'Search user bind password',
disable: false,
value: 'grafana'
}
default['grafana']['ldap']['[servers]']['search_filter'] = {
comment: 'Search filter, for example "(cn=%s)" or "(sAMAccountName=%s)"',
disable: false,
value: '"(cn=%s)"'
}
default['grafana']['ldap']['[servers]']['search_base_dns'] = {
comment: 'An array of base dns to search through',
disable: false,
value: ['dc=grafana,dc=org']
}
default['grafana']['ldap']['servers.attributes'] = {
name: { value: '"givenName"' },
surname: { value: '"sn"' },
username: { value: '"cn"' },
member_of: { value: '"memberOf"' },
email: { value: '"email"' }
}
default['grafana']['ldap_mappings'] = [
{
group_dn: {
comment: 'Map ldap groups to grafana org roles',
disable: false,
value: '"cn=admins,ou=ACLs,dc=grafana,dc=org"'
},
org_role: {
disable: false,
value: '"Admin"'
},
org_id: {
comment: 'The Grafana organization database id, optional, ' \
'if left out the default org (id 1) will be used',
disable: true,
value: 1
}
},
{
group_dn: {
disable: false,
value: '"cn=users,dc=comugrafana,dc=org"'
},
org_role: {
disable: false,
value: '"Editor"'
}
},
{
group_dn: {
comment: 'If you want to match all (or no ldap groups) then you can use wildcard',
disable: false,
value: '"*"'
},
org_role: {
disable: false,
value: '"Viewer"'
}
}
]
18 changes: 14 additions & 4 deletions libraries/ini_helper.rb
Expand Up @@ -2,10 +2,20 @@ module GrafanaCookbook
module IniHelper
def self.format_config(config)
output = []
config.each do |section, groups|
output << format_section(section)
groups.each do |key, value|
output << format_kv(key, value)
case config
when Hash
config.each do |section, groups|
output << format_section(section)
groups.each do |key, value|
output << format_kv(key, value)
end
end
else
config.each do |groups|
output << format_section('[servers.group_mappings]')
groups.each do |key, value|
output << format_kv(key, value)
end
end
end
output.join "\n"
Expand Down
12 changes: 12 additions & 0 deletions recipes/_ldap_config.rb
@@ -0,0 +1,12 @@
ldap = node['grafana']['ldap'].dup
mapping = node['grafana']['ldap_mappings'].dup
verbose_logging = node['grafana']['ldap_verbose_logging']

template node['grafana']['ini']['auth.ldap']['config_file']['value'] do
source 'ldap.toml.erb'
variables verbose_logging: verbose_logging, config: ldap, mapping: mapping
owner 'root'
group 'root'
mode '0644'
notifies :restart, 'service[grafana-server]', :delayed
end
6 changes: 5 additions & 1 deletion recipes/default.rb
Expand Up @@ -69,5 +69,9 @@
owner 'root'
group 'root'
mode '0644'
notifies :restart, 'service[grafana-server]', :immediately
notifies :restart, 'service[grafana-server]', :delayed
end

unless node['grafana']['ini']['auth.ldap']['enabled']['value'] == false
include_recipe 'grafana::_ldap_config'
end
136 changes: 131 additions & 5 deletions spec/unit/default_spec.rb
Expand Up @@ -69,13 +69,20 @@
mode: '0644',
user: 'root'
)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[database\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^host = 127.0.0.1:3306/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^# For "postgres" only, either "disable", "require" or "verify-full"/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^;ssl_mode = disable/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^# For sqlite3 only, path relative to data_path setting/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^path = grafana.db/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[server\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^protocol = http/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^http_port = 3000/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^domain = localhost/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[paths\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^logs = /var/log/grafana})
end

it 'generate grafana-server environment vars' do
Expand All @@ -85,6 +92,10 @@
it 'enable grafana-server service' do
expect(chef_run).to enable_service('grafana-server')
end

it 'does not include recipe _ldap_config' do
expect(chef_run).to_not include_recipe('grafana::_ldap_config')
end
end

context 'with no webserver' do
Expand Down Expand Up @@ -116,6 +127,67 @@
expect(chef_run).to include_recipe 'grafana::_install_file'
end

it 'generate grafana.ini' do
expect(chef_run).to create_template('/etc/grafana/grafana.ini').with(
mode: '0644',
user: 'root'
)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[database\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^host = 127.0.0.1:3306/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^;ssl_mode = disable/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^path = grafana.db/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[server\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^protocol = http/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^http_port = 3000/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^domain = localhost/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[paths\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^logs = /var/log/grafana})
end
it 'does not include recipe _ldap_config' do
expect(chef_run).to_not include_recipe('grafana::_ldap_config')
end
end

context 'with LDAP authentication enabled' do
let(:chef_run) do
ChefSpec::SoloRunner.new(chef_solo_opts) do |node|
node.set['grafana']['ini']['auth.ldap']['enabled']['value'] = true
end.converge described_recipe
end
before do
stub_command 'which nginx'
end

it 'installs grafana package' do
if platform == 'centos'
expect(chef_run).to install_rpm_package("grafana-#{grafana_version}")
else
expect(chef_run).to install_dpkg_package("grafana-#{grafana_version}")
end
end

it 'loads grafana::_nginx recipe' do
expect(chef_run).to include_recipe 'grafana::_nginx'
end

it 'loads grafana::_install_file recipe' do
expect(chef_run).to include_recipe 'grafana::_install_file'
end

it 'loads grafana::_ldap_config recipe' do
expect(chef_run).to include_recipe 'grafana::_ldap_config'
end

it 'create log and data directories' do
expect(chef_run).to create_directory('/var/lib/grafana').with(mode: '0755')
expect(chef_run).to create_directory('/var/log/grafana').with(mode: '0755')
end

it 'generate grafana.ini' do
expect(chef_run).to create_template('/etc/grafana/grafana.ini').with(
mode: '0644',
Expand All @@ -124,10 +196,64 @@
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[database\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^host = 127.0.0.1:3306/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^# For "postgres" only, either "disable", "require" or "verify-full"/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^;ssl_mode = disable/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^# For sqlite3 only, path relative to data_path setting/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^path = grafana.db/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[server\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^protocol = http/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^http_port = 3000/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^domain = localhost/)

expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(/^\[paths\]/)
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^data = /var/lib/grafana})
expect(chef_run).to render_file('/etc/grafana/grafana.ini').with_content(%r{^logs = /var/log/grafana})
end

it 'generate ldap.toml' do
expect(chef_run).to create_template('/etc/grafana/ldap.toml').with(
mode: '0644',
user: 'root'
)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^verbose_logging = false/)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^\[\[servers\]\]/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^host = "127.0.0.1"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^port = 389/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^use_ssl = false/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^ssl_skip_verify = false/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^bind_dn = "cn=admin,dc=grafana,dc=org"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^bind_password = grafana/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^search_filter = "\(cn=%s\)"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^search_base_dns = \["dc=grafana,dc=org"\]/)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^\[servers.attributes\]/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^name = "givenName"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^surname = "sn"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^username = "cn"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^member_of = "memberOf"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^email = "email"/)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^\[\[servers.group_mappings\]\]/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^group_dn = "cn=admins,ou=ACLs,dc=grafana,dc=org"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^org_role = "Admin"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^;org_id = 1/)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^\[\[servers.group_mappings\]\]/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^group_dn = "cn=users,dc=comugrafana,dc=org"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^org_role = "Editor"/)

expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^\[\[servers.group_mappings\]\]/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^group_dn = "*"/)
expect(chef_run).to render_file('/etc/grafana/ldap.toml').with_content(/^org_role = "Viewer"/)
end

it 'generate grafana-server environment vars' do
expect(chef_run).to create_template('/etc/default/grafana-server')
end

it 'enable grafana-server service' do
expect(chef_run).to enable_service('grafana-server')
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions templates/default/ldap.toml.erb
@@ -0,0 +1,13 @@
#
# This file was generated by Chef for <%= node['fqdn'] %> and Grafana <%= node['grafana']['version'] %>.
# Do not modify this file by hand!
#
# full documentation: http://docs.grafana.org/installation/configuration/
#

# Set to true to log user information returned from LDAP
verbose_logging = <%= @verbose_logging %>
<%= GrafanaCookbook::IniHelper.format_config @config %>
<%= GrafanaCookbook::IniHelper.format_config @mapping %>

0 comments on commit 5d1de96

Please sign in to comment.