<commit_before>
    misc = require 'mecano/lib/misc'
    module.exports = []
    module.exports.push 'phyla/core/yum'
    module.exports.push 'phyla/core/ssh'
    module.exports.push 'phyla/core/ntp'
    module.exports.push 'phyla/core/openldap_client'

# Kerberos Client

Kerberos is a network authentication protocol. It is designed 
to provide strong authentication for client/server applications 
by using secret-key cryptography.

This module install the client tools written by the [Massachusetts 
Institute of Technology](http://web.mit.edu).

## Configuration

*   `krb5_client.kadmin_principal` (string, required)
*   `krb5_client.kadmin_password` (string, required)
*   `krb5_client.kadmin_server` (string, required)
*   `krb5_client.realm` (string, required)
*   `krb5_client.etc_krb5_conf` (object)
    Object representing the full ini file in "/etc/krb5.conf". It is
    generated by default.
*   `krb5_client.sshd` (object)
    Properties inserted in the "/etc/ssh/sshd_config" file.

Example:
```json
{
  "krb5_client": {
    "realm": "ADALTAS.COM",
    "kdc": "krb5.hadoop",
    "kadmin_server": "krb5.hadoop",
    "kadmin_principal": "wdavidw/admin@ADALTAS.COM",
    "kadmin_password": "<PASSWORD>"
  }
}
```

    module.exports.push module.exports.configure = (ctx) ->
      {realm, kadmin_principal, kadmin_password, kadmin_server} = ctx.config.krb5_client
      throw new Error "Kerberos property kadmin_principal is required" unless kadmin_principal
      throw new Error "Kerberos property kadmin_password is required" unless kadmin_password
      throw new Error "Kerberos property kadmin_server is required" unless kadmin_server
      throw new Error "Kerberos property realm is required" unless realm
      ctx.config.krb5_client.realm = ctx.config.krb5_client.realm.toUpperCase()
      unless ctx.config.krb5_client.etc_krb5_conf
        REALM = ctx.config.krb5_client.realm
        realm = REALM.toLowerCase()
        etc_krb5_conf =
          'logging':
            'default': 'SYSLOG:INFO:LOCAL1'
            'kdc': 'SYSLOG:NOTICE:LOCAL1'
            'admin_server': 'SYSLOG:WARNING:LOCAL1'
          'libdefaults': 
            'default_realm': REALM
            'dns_lookup_realm': false
            'dns_lookup_kdc': false
            'ticket_lifetime': '24h'
            'renew_lifetime': '7d'
            'forwardable': true
          'realms': {}
          'domain_realm': {}
          'appdefaults':
            'pam':
              'debug': false
              'ticket_lifetime': 36000
              'renew_lifetime': 36000
              'forwardable': true
              'krb4_convert': false
        etc_krb5_conf.realms["#{REALM}"] = 
          'kdc': ctx.config.krb5_client.kdc or realm
          'admin_server': ctx.config.krb5_client.kadmin_server or realm
          'default_domain': ctx.config.krb5_client.default_domain or realm
        etc_krb5_conf.domain_realm[".#{realm}"] = REALM
        etc_krb5_conf.domain_realm["#{realm}"] = REALM
        ctx.config.krb5_client.etc_krb5_conf = etc_krb5_conf
      ctx.config.krb5_client.sshd ?= {}
      ctx.config.krb5_client.sshd = misc.merge
        ChallengeResponseAuthentication: 'yes'
        KerberosAuthentication: 'yes'
        KerberosOrLocalPasswd: 'yes'
        KerberosTicketCleanup: 'yes'
        GSSAPIAuthentication: 'yes'
        GSSAPICleanupCredentials: 'yes'
      , ctx.config.krb5_client.sshd

## Install

The package "krb5-workstation" is installed.

    module.exports.push name: 'Krb5 client # Install', timeout: -1, callback: (ctx, next) ->
      ctx.service
        name: 'krb5-workstation'
      , (err, serviced) ->
        next err, if serviced then ctx.OK else ctx.PASS

## Configure

Modify the Kerberos configuration file in "/etc/krb5.conf". Note, 
this action wont be run if the server host a Kerberos server. 
This is to avoid any conflict where both modules would try to write 
their own configuration one. We give the priority to the server module 
which create a Kerberos file with complementary information.

    module.exports.push name: 'Krb5 client # Configure', timeout: -1, callback: (ctx, next) ->
      # Kerberos config is also managed by the kerberos server action.
      ctx.log 'Check who manage /etc/krb5.conf'
      return next null, ctx.INAPPLICABLE if ctx.has_module 'phyla/core/krb5_server'
      {etc_krb5_conf} = ctx.config.krb5_client
      ctx.log 'Update /etc/krb5.conf'
      ctx.ini
        content: etc_krb5_conf
        destination: '/etc/krb5.conf'
        stringify: misc.ini.stringify_square_then_curly
      , (err, written) ->
        return next err, if written then ctx.OK else ctx.PASS

## Host Principal

Create a user principal for this host. The principal is named like "host/{hostname}@{realm}".

    module.exports.push name: 'Krb5 client # Host Principal', timeout: -1, callback: (ctx, next) ->
      {realm, etc_krb5_conf, kadmin_principal, kadmin_password, kadmin_server} = ctx.config.krb5_client
      krb5_admin_servers = for realm, config of etc_krb5_conf.realms then  config.admin_server
      ctx.waitIsOpen krb5_admin_servers, 88, (err) ->
        ctx.krb5_addprinc
          principal: "host/#{ctx.config.host}@#{realm}"
          randkey: true<commit_msg>Wait exec instead of port listening for krb5 client<commit_after>
    misc = require 'mecano/lib/misc'
    module.exports = []
    module.exports.push 'phyla/core/yum'
    module.exports.push 'phyla/core/ssh'
    module.exports.push 'phyla/core/ntp'
    module.exports.push 'phyla/core/openldap_client'

# Kerberos Client

Kerberos is a network authentication protocol. It is designed 
to provide strong authentication for client/server applications 
by using secret-key cryptography.

This module install the client tools written by the [Massachusetts 
Institute of Technology](http://web.mit.edu).

## Configuration

*   `krb5_client.kadmin_principal` (string, required)
*   `krb5_client.kadmin_password` (string, required)
*   `krb5_client.kadmin_server` (string, required)
*   `krb5_client.realm` (string, required)
*   `krb5_client.etc_krb5_conf` (object)
    Object representing the full ini file in "/etc/krb5.conf". It is
    generated by default.
*   `krb5_client.sshd` (object)
    Properties inserted in the "/etc/ssh/sshd_config" file.

Example:
```json
{
  "krb5_client": {
    "realm": "ADALTAS.COM",
    "kdc": "krb5.hadoop",
    "kadmin_server": "krb5.hadoop",
    "kadmin_principal": "wdavidw/admin@AD<EMAIL>.COM",
    "kadmin_password": "<PASSWORD>"
  }
}
```

    module.exports.push module.exports.configure = (ctx) ->
      {realm, kadmin_principal, kadmin_password, kadmin_server} = ctx.config.krb5_client
      throw new Error "Kerberos property kadmin_principal is required" unless kadmin_principal
      throw new Error "Kerberos property kadmin_password is required" unless kadmin_password
      throw new Error "Kerberos property kadmin_server is required" unless kadmin_server
      throw new Error "Kerberos property realm is required" unless realm
      ctx.config.krb5_client.realm = ctx.config.krb5_client.realm.toUpperCase()
      unless ctx.config.krb5_client.etc_krb5_conf
        REALM = ctx.config.krb5_client.realm
        realm = REALM.toLowerCase()
        etc_krb5_conf =
          'logging':
            'default': 'SYSLOG:INFO:LOCAL1'
            'kdc': 'SYSLOG:NOTICE:LOCAL1'
            'admin_server': 'SYSLOG:WARNING:LOCAL1'
          'libdefaults': 
            'default_realm': REALM
            'dns_lookup_realm': false
            'dns_lookup_kdc': false
            'ticket_lifetime': '24h'
            'renew_lifetime': '7d'
            'forwardable': true
          'realms': {}
          'domain_realm': {}
          'appdefaults':
            'pam':
              'debug': false
              'ticket_lifetime': 36000
              'renew_lifetime': 36000
              'forwardable': true
              'krb4_convert': false
        etc_krb5_conf.realms["#{REALM}"] = 
          'kdc': ctx.config.krb5_client.kdc or realm
          'admin_server': ctx.config.krb5_client.kadmin_server or realm
          'default_domain': ctx.config.krb5_client.default_domain or realm
        etc_krb5_conf.domain_realm[".#{realm}"] = REALM
        etc_krb5_conf.domain_realm["#{realm}"] = REALM
        ctx.config.krb5_client.etc_krb5_conf = etc_krb5_conf
      ctx.config.krb5_client.sshd ?= {}
      ctx.config.krb5_client.sshd = misc.merge
        ChallengeResponseAuthentication: 'yes'
        KerberosAuthentication: 'yes'
        KerberosOrLocalPasswd: 'yes'
        KerberosTicketCleanup: 'yes'
        GSSAPIAuthentication: 'yes'
        GSSAPICleanupCredentials: 'yes'
      , ctx.config.krb5_client.sshd

## Install

The package "krb5-workstation" is installed.

    module.exports.push name: 'Krb5 client # Install', timeout: -1, callback: (ctx, next) ->
      ctx.service
        name: 'krb5-workstation'
      , (err, serviced) ->
        next err, if serviced then ctx.OK else ctx.PASS

## Configure

Modify the Kerberos configuration file in "/etc/krb5.conf". Note, 
this action wont be run if the server host a Kerberos server. 
This is to avoid any conflict where both modules would try to write 
their own configuration one. We give the priority to the server module 
which create a Kerberos file with complementary information.

    module.exports.push name: 'Krb5 client # Configure', timeout: -1, callback: (ctx, next) ->
      # Kerberos config is also managed by the kerberos server action.
      ctx.log 'Check who manage /etc/krb5.conf'
      return next null, ctx.INAPPLICABLE if ctx.has_module 'phyla/core/krb5_server'
      {etc_krb5_conf} = ctx.config.krb5_client
      ctx.log 'Update /etc/krb5.conf'
      ctx.ini
        content: etc_krb5_conf
        destination: '/etc/krb5.conf'
        stringify: misc.ini.stringify_square_then_curly
      , (err, written) ->
        return next err, if written then ctx.OK else ctx.PASS

## Host Principal

Create a user principal for this host. The principal is named like "host/{hostname}@{realm}".

    module.exports.push name: 'Krb5 client # Host Principal', timeout: -1, callback: (ctx, next) ->
      {realm, etc_krb5_conf, kadmin_principal, kadmin_password, kadmin_server} = ctx.config.krb5_client
      krb5_admin_servers = for realm, config of etc_krb5_conf.realms then  config.admin_server
      # ctx.waitIsOpen krb5_admin_servers, 88, (err) ->
      ctx.waitForExecution "kadmin -p #{kadmin_principal} -s #{kadmin_server} -w #{kadmin_password} -q 'listprincs'", (err) ->
        return next err if err
        ctx.krb5_addprinc
          principal: "host/#{ctx.config.host}@#{realm}"
          randkey: true
{'fraction_non_alphanumeric': 0.10386201724784402, 'fraction_numerical': 0.013404574428196476, 'mean_word_length': 2.988411214953271, 'pattern_counts': {'":': 12, '<': 6, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5404432', 'n_tokens_mistral': 3566, 'n_tokens_neox': 3500, 'n_words': 843}