UNPKG

masson

Version:

Module execution engine for cluster deployments.

313 lines (282 loc) 13.1 kB
# Kerberos Server Install Install the MIT Kerberos server with an OpenLDAP Back-End. Usefull server commands: * Backup the db: `kdb5_util dump /path/to/dumpfile` * Initialize realm: `kdb5_ldap_util -D "cn=Manager,dc=adaltas,dc=com" -w test create -subtrees "ou=kerberos,ou=services,dc=adaltas,dc=com" -r ADALTAS.COM -s -P test` * Load the db: `kdb5_util load -update /path/to/dumpfile` * Stash password: `kdb5_ldap_util -D "cn=Manager,dc=adaltas,dc=com" -w test stashsrvpw -f /etc/krb5.d/stash.keyfile cn=krbadmin,ou=users,dc=adaltas,dc=com` Resources: * [Kerberos with LDAP backend on centos](http://itdavid.blogspot.fr/2012/05/howto-centos-62-kerberos-kdc-with.html) * [Propagation](http://www-old.grantcohoe.com/guides/services/krb5-kdc) * [Replication](http://tldp.org/HOWTO/Kerberos-Infrastructure-HOWTO/server-replication.html) * [Kerberos with LDAP backend on ubuntu](http://labs.opinsys.com/blog/2010/02/05/setting-up-openldap-kerberos-on-ubuntu-10-04-lucid/) * [On Load Balancers and Kerberos](https://ssimo.org/blog/id_019.html) * [Kerberos With LDAP on centos 7](http://www.rjsystems.nl/en/2100-d6-kerberos-openldap-provider.php) export default header: 'Kerberos Server Install', handler: ({options}) -> ## IPTables | Service | Port | Proto | Parameter | |------------|------|-------|--------------------------------------| | kadmin | 749 | tcp | `kdc_conf.kdcdefaults.kadmind_port` | | krb5kdc | 88 | upd | `kdc_conf.kdcdefaults.kdc_ports` | | krb5kdc | 88 | tcp | `kdc_conf.kdcdefaults.kdc_tcp_ports` | IPTables rules are only inserted if the parameter "iptables.action" is set to "start" (default value). rules = [] add_default_kadmind_port = false add_default_kdc_ports = false add_default_kdc_tcp_ports = false for realm, config of options.kdc_conf.realms if config.kadmind_port rules.push chain: 'INPUT', jump: 'ACCEPT', dport: config.kadmind_port, protocol: 'tcp', state: 'NEW', comment: "Kerberos administration server (kadmind daemon)" else add_default_kadmind_port = true if config.kdc_ports for port in config.kdc_ports.split /\s,/ rules.push chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'udp', state: 'NEW', comment: "Kerberos Authentication Service and Key Distribution Center (krb5kdc daemon)" else add_default_kdc_ports = true if config.kdc_tcp_ports kdc_tcp_ports = true for port in config.kdc_ports.split /\s,/ rules.push chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'tcp', state: 'NEW', comment: "Kerberos Authentication Service and Key Distribution Center (krb5kdc daemon)" else add_default_kdc_tcp_ports = true if add_default_kadmind_port port = options.kdc_conf.kdcdefaults.kadmind_port or '749' rules.push chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'tcp', state: 'NEW', comment: "Kerberos administration server (kadmind daemon)" if add_default_kdc_ports for port in (options.kdc_conf.kdcdefaults.kdc_ports or '88').split /\s,/ rules.push chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'udp', state: 'NEW', comment: "Kerberos Authentication Service and Key Distribution Center (krb5kdc daemon)" if add_default_kdc_tcp_ports for port in (options.kdc_conf.kdcdefaults.kdc_tcp_ports or '88').split /\s,/ rules.push chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'tcp', state: 'NEW', comment: "Kerberos Authentication Service and Key Distribution Center (krb5kdc daemon)" @tools.iptables header: 'IPTables' if: options.iptables rules: rules ## Package @service name: 'krb5-pkinit-openssl' @service name: 'krb5-server-ldap' startup: true chk_name: 'krb5kdc' @service name: 'krb5-server-ldap' startup: true chk_name: 'kadmin' @service name: 'krb5-workstation' ## Configuration The following files are updated: * "/etc/krb5.conf" client configuration * "/var/kerberos/krb5kdc/kadm5.acl" acl definition * "/var/kerberos/krb5kdc/kdc.conf" kdc server configuration * "/etc/sysconfig/kadmin" kadmin default realm * "/etc/sysconfig/krb5kdc" kdc default realm @call header: 'Configuration', -> any_realm = Object.keys(options.kdc_conf.realms)[0] @file write: for realm of options.kdc_conf.realms match: ///^\*/\w+@#{misc.regexp.escape realm}\s+\*///mg replace: "*/admin@#{realm} *" append: true target: '/var/kerberos/krb5kdc/kadm5.acl' backup: true @file.ini content: options.kdc_conf target: '/var/kerberos/krb5kdc/kdc.conf' stringify: misc.ini.stringify_brackets_then_curly backup: true @file target: '/etc/sysconfig/kadmin' match: /^KRB5REALM=.*$/mg replace: "KRB5REALM=#{any_realm}" backup: true @file target: '/etc/sysconfig/krb5kdc' match: /^KRB5REALM=.*$/mg replace: "KRB5REALM=#{any_realm}" backup: true @call if: -> @status() , -> @call 'masson/core/openldap_client/wait', options.wait_ldap_client @service srv_name: 'krb5kdc' state: 'restarted' @service srv_name: 'kadmin' state: 'restarted' ## Wait @call 'masson/core/openldap_client/wait' ## Ldap Krb5 entries @call header: 'LDAP DN', -> for realm, config of options.kdc_conf.realms continue unless config.database_module {kdc_master_key, ldap_kerberos_container_dn, ldap_servers} = options.kdc_conf.dbmodules[config.database_module] ldap_server = ldap_servers.split(' ')[0] @wait.execute header: 'Wait DN Access' cmd: """ ldapsearch -x -LLL \ -H #{ldap_server} -D \"#{options.root_dn}\" -w #{options.root_password} \ -b \"#{ldap_kerberos_container_dn}\" """ code_skipped: 32 @system.execute header: 'Realm Detection' shy: true cmd: """ ldapsearch -x \ -H #{ldap_server} -D \"#{options.root_dn}\" -w #{options.root_password} \ -b \"cn=#{realm},#{ldap_kerberos_container_dn}\" """ code_skipped: 32 # Note, kdb5_ldap_util is using /etc/krb5.conf (server version) @system.execute header: 'Realm Initialization' if: not options.admin[realm].ha or options.admin[realm].master cmd: """ kdb5_ldap_util \ -D \"#{options.root_dn}\" -w #{options.root_password} \ create -subtrees \"#{ldap_kerberos_container_dn}\" -r #{realm} -s -P #{kdc_master_key} """ unless: -> @status -1 @call header: 'LDAP Stash password', -> ssh = @ssh options.ssh for name, dbmodule of options.kdc_conf.dbmodules then do(name, dbmodule) => @log message: "Stash key file is: #{dbmodule.ldap_service_password_file}" keyfileContent = null @call (_, callback) -> @log message: 'Read current keyfile if it exists' @fs.readFile target: "#{dbmodule.ldap_service_password_file}" encoding: 'utf8' , (err, {data}) -> return callback null, true if err and err.code is 'ENOENT' return callback err if err keyfileContent = data callback null, false @system.mkdir target: path.dirname(dbmodule.ldap_service_password_file) if: -> @status -1 @call (_, callback) -> @log message: 'Stash password into local file for kadmin dn' ssh.shell (err, stream) => return callback err if err cmd = "#{if options.sudo then 'sudo'} kdb5_ldap_util -D \"#{options.root_dn}\" -w #{options.root_password} stashsrvpw -f #{dbmodule.ldap_service_password_file} #{dbmodule.ldap_kadmind_dn}" @log message: "Run `#{cmd}`" reentered = done = false stream.write "#{cmd}\n" stream.on 'data', (data, stderr) => # @log[if stderr then 'err' else 'out'].write data data = data.toString() if /Password for/.test data @log "Enter Password", level: 'INFO' stream.write "#{dbmodule.ldap_kadmind_password}\n" else if /Re-enter password for/.test data @log "Re-enter Password", level: 'INFO' stream.write "#{dbmodule.ldap_kadmind_password}\n\n" reentered = true else if reentered and not done done = true stream.end 'exit\n' stream.on 'exit', -> callback() @call (_, callback) -> return callback null, true unless keyfileContent @fs.readFile target: "#{dbmodule.ldap_service_password_file}" encoding: 'utf8' , (err, {data}) -> return callback err if err modified = if keyfileContent is data then false else true callback null, keyfileContent isnt data @call header: 'HA', -> {ha_deploy_master, root, ssh, sudo} = options @each options.admin, ({options}, next) -> realm_data = '' config = options.value return next() unless config.ha and not config.master @call (_, next_cb) -> node = nikita() @log message: "Delegate to: #{ha_deploy_master[config.realm]}" node.ssh.open host: ha_deploy_master[config.realm], ssh node.wait.exist target: "/var/kerberos/krb5kdc/.k5.#{config.realm}" node.call (_, cb) -> node.fs.readFile "/var/kerberos/krb5kdc/.k5.#{config.realm}", sudo: sudo, (err, {data}) => realm_data = data node.next cb node.ssh.close() node.next next_cb @call -> @fs.writeFile target: "/var/kerberos/krb5kdc/.k5.#{config.realm}" content: realm_data @next next @call header: 'Log', -> @file.touch target: '/var/log/krb5kdc.log' uid: 'root' @file.touch target: '/var/log/kadmind.log' uid: 'root' @file target: '/etc/rsyslog.conf' write: [ match: /.*krb5kdc.*/mg replace: 'if $programname == \'krb5kdc\' then /var/log/krb5kdc.log' append: '### RULES ###' , match: /.*kadmind.*/mg replace: 'if $programname == \'kadmind\' then /var/log/kadmind.log' append: '### RULES ###' ] @service.start name: 'krb5kdc' if: -> @status -1 @service.start name: 'kadmin' if: -> @status -2 @service srv_name: 'rsyslog' state: 'restarted' if: -> @status -3 @call header: 'Admin principal', -> for realm, admin of options.admin @krb5.addprinc if: admin.kadmin_principal # TODO: remove once krb5 client & server configs are splitted realm: realm principal: admin.kadmin_principal password: admin.kadmin_password @call header: 'Principals', -> for realm, config of options.kdc_conf.realms admin = options.admin[realm] # continue unless config.kadmin_principal # TODO: remove once krb5 client & server configs are splitted for principal in admin.principals @krb5.addprinc principal # TODO: no time to work on this, the idea is to modified kadmin startup # script to handle multiple kadmin server. Note, for `killproc` to stop # all instances, it seems that we need to set multiple pid files, here # a exemple: `/usr/sbin/kadmind -r USERS.ADALTAS.COM -P /var/run/kadmind1.pid` # write = [] # write.push match: /^(\s+)(daemon\s+.*)/mg, replace: "$1#$2" # for realm, _ of options.kdc_conf # replace: " daemon ${kadmind} -r" # append: /\s+#daemon\s+.*/ # @file # target: '/etc/init.d/kadmin' # write: write ## Dependencies fs = require 'ssh2-fs' path = require('path').posix each = require 'each' misc = require '@nikitajs/core/lib/misc' nikita = require 'nikita' mixme = require 'mixme' ## Notes Renewable tickets is per default disallowed in the most linux distributions. This can be done per: ```bash kadmin.local: modprinc -maxrenewlife 7day krbtgt/YOUR_REALM kadmin.local: modprinc -maxrenewlife 7day +allow_renewable hue/FQRN ```