Introduction

Before Ambari 2.0.0, configuring an Ambari cluster to use Kerberos involved setting up the Kerberos client infrastructure on each host, creating the required identities, generating and distributing the needed keytabs files, and updating the necessary configuration properties. On a small cluster this may not seem to be too large of an effort; however as the size of the cluster increases, so does the amount of work that is involved.

This is where Ambari’s Automated Kerberization facility can help. It performs all of these steps and also helps to maintain the cluster as new services and hosts are added.

The Automated Kerberization can be invoked using Ambari’s REST API as well as the Enable Kerberos Wizard in the Ambari UI.

How it works

Stacks and services that can utilize Kerberos credentials for authentication must have a Kerberos Descriptor declaring required Kerberos identities and how to update configurations. The Ambari infrastructure uses this data, and any updates applied by an administrator, to perform Kerberos related operations such as initially enabling Kerberos, enabling Kerberos for on hosts and added components, regenerating credentials, and disabling Kerberos. 

 It should be notated that it Ambari is required to be installed on a registered host. Also, the Kerberos service is required to be installed on all hosts of the cluster before any automated tasks can be performed. If using the Ambari UI, this should happen as part of the relevant wizard workflow. 

Enabling Kerberos

When enabling Kerberos, all of the services in the cluster are expected to be stopped. The main reason for this is to avoid state issues as the services are stopped and then started when the cluster is transitioning to be Kerberized. The following steps are taken to enable Kerberos on the cluster en masse:

  1. Create or update accounts in the configured KDC (or Active Directory)
  2. Generate keytab files and distribute them to the appropriate hosts
  3. Update relevant configurations

Adding Components

If Automated Kerberization was enabled for the Ambari cluster, whenever new components are added, the will automatically be configured for Kerberos and any necessary principals and keytabs will be generated and distributed. For each new component, the following steps will occur before the component is installed and started:

  1. Update relevant configurations
  2. Create or update accounts in the configured KDC (or Active Directory)
  3. Generate keytab files and distribute them to the appropriate hosts

Adding Hosts

When adding a new host, the Kerberos client must be installed on it. This does not happen automatically, however the Add Host Wizard in the Ambari UI will will perform this step if Automated Kerberization was enabled for the Ambari cluster. Once host is added, generally one or more components are installed on it - see Adding Components.

Regenerating Keytabs

Once a cluster has Automated Kerberization enabled, it may be necessary to regenerate keytabs. There are two options related to regenerating keytabs: all or missing.

In any case, the affected services should be restarted after the following regeneration process is complete:

  1. Create missing or update existing accounts in the configured KDC (or Active Directory)
  2. Generate keytab files and distribute them to the appropriate hosts

Disabling Kerberos

In the event Kerberos needs to be removed from the Ambari cluster, the Ambari will remove the managed Kerberos identities, keytab files, and configuration. The Ambari UI will perform the steps of stopping and starting the services as well as removing the Kerberos service, however this will need to be done manually, otherwise.

The Kerberos Descriptor

The Kerberos Descriptor is a JSON-formatted text file containing information needed by Ambari to enable or disable Kerberos for a stack and its services. This file must be named kerberos.json and should be in the root directory of the relevant stack or service. Kerberos Descriptors are meant to be hierarchical such that details in the stack-level descriptor can be overwritten (or updated) by details in the service-level descriptors.

For the services in a stack to be Kerberized, there must be a stack-level Kerberos Descriptor. This ensures that even if a common service has a Kerberos Descriptor, it may not be Kerberized unless the relevant stack indicates that supports Kerberos by having a stack-level Kerberos Descriptor.

For a component of a service to be Kerberized, there must be an entry for it in its containing service's service-level descriptor. This allows for some of a services' components to be managed and other components of that service to be ignored by the automated Kerberos facility.

Kerberos Descriptors are inherited from the base stack or service, but may be overridden as a full descriptor - partial descriptors are not allowed.

A complete descriptor (which is built using the stack-level descriptor, the service-level descriptors, and any updates from user input) has the following structure:

  • Stack-level Properties
  • Stack-level Identities
  • Stack-level Configurations
  • Stack-level Auth-to-local-properties
  • Services
    • Service-level Identities
    • Service-level Configurations
    • Service-level Auth-to-local-properties
    • Components
      • Component-level Identities
      • Component-level Configurations
      • Component-level Auth-to-local-properties

Each level of the descriptor inherits the data from its parent. This data, however, may be overridden if necessary. For example, a component will inherit the configurations and identities of its container service; which in turn inherits the configurations and identities from the stack.

Components of a Kerberos Descriptor

Stack-level Properties

Stack-level properties is an optional set of name/value pairs that can be used in variable replacements. For example, if a property named "property1" exists with the value of "value1", then any instance of "${property1}" within a configuration property name or configuration property value will be replaced with "value1".

This property is only relevant in the stack-level Kerberos Descriptor and may not be overridden by lower-level descriptors.

Stack-level Identities

Stack-level identities is an optional identities block containing a list of zero or more identity descriptors that are common among all services in the stack. An example of such an identity is the Ambari smoke test user, which is used by all services to perform service check operations. Service- and component-level identities may reference (and specialize) stack-level identities using the identity’s name with a forward slash (/) preceding it. For example if there was a stack-level identity with the name "smokeuser", then a service or a component may create an identity block that references and specializes it by setting its name to "/smokeuser" and overriding its properties as necessary. This does not override the stack-level identity, it essentially creates a copy of it and updates the copy's properties. 

Stack-level Auth-to-local-properties

Stack-level auth-to-local-properties is an optional list of zero or more configuration property specifications (config-type/property_name[|concatenation_scheme]) indicating which properties contain auth-to-local rule sets and how to concatenate the rules to meet the property specifications. These sets are dynamically updated using the details from the identities used when Kerberizing the cluster and concatenated as indicated.  The concatenation scheme value is optional.

If specified one of the following schemes must be specified:

  • new_lines - rules in the rule set are separated by a new line (\n)
  • new_lines_escaped - rules in the rule set are separated by a \ and a new line (\ \n)
  • spaces - rules in the rule set are separated by a whitespace character (effectively placing all rules in a single line)

If not specified, the default concatenation scheme is new_lines.

Examples

Service site property using the default concatenation scheme

 core-site/hadoop.security.auth_to_local

Service site property explicitly using the escaped new lines concatenation scheme

startup.properties/http.authentication.kerberos.name.rules|new_lines_escaped

Stack-level Configurations

Stack-level configurations is an optional configurations block containing a list of zero or more configuration descriptors that are common among all services in the stack. Configuration descriptors are overridable due to the structure of the data.  However overriding configuration properties may create undesired behavior since it is not known until after the Kerberization process is complete what value a property will have.

Services

Services is a list of zero or more service descriptors. A stack-level Kerberos Descriptor should not list any services; however a service-level Kerberos Descriptor should contain at least one.

Service-level Identities

Service-level identities is an optional identities block containing list of zero or more identity descriptors that are common among all components of the service. Component-level identities may reference (and specialize) service-level identities using a relative path to the identity (the identity’s name with a two dots and forward slash (../) preceding it) or an absolute path to it (/service_name/identity_name). For example if there was a service-level identity with the name "service_identity", then a child component may create an identity block that references and specializes it by setting its name to "../service_identity" or "/service_name/service_identity" and overriding any values as necessary. This does not override the service-level identity, it essentially creates a copy of it and updates the copy's properties. 

 

Note: By using the absolute path to an identity, any service-level identity may be referenced by any other service or component.

Service-level Configurations

Service-level configurations is an optional configurations block listing of zero or more configuration descriptors that are common among all components within a service. Configuration descriptors are overridable due to the structure of the data.  However overriding configuration properties may create undesired behavior since it is not known until after the Kerberization process is complete what value a property will have.

Service-level Auth-to-local-properties

Service-level auth-to-local-properties is an optional list of zero or more configuration property specifications (config-type/property_name[|concatenation_scheme]) indicating which properties contain auth-to-local rule sets and how to concatenate the rules to meet the property specifications. These sets are dynamically updated using the details from the identities used when Kerberizing the cluster and concatenated as indicated.  The concatenation scheme value is optional.

If specified one of the following schemes must be specified:

  • new_lines - rules in the rule set are separated by a new line (\n)
  • new_lines_escaped - rules in the rule set are separated by a \ and a new line (\ \n)
  • spaces - rules in the rule set are separated by a whitespace character (effectively placing all rules in a single line)

If not specified, the default concatenation scheme is new_lines.

Examples

Service site property using the default concatenation scheme 

 core-site/hadoop.security.auth_to_local 

Service site property explicitly using the escaped new lines concatenation scheme 

startup.properties/http.authentication.kerberos.name.rules|new_lines_escaped

Components

Components is a list of zero or more component descriptor blocks. 

Component-level Identities

 Component-level identities is an optional identities block containing a list of zero or more identity descriptors that are specific to the component. A Component-level identity may be referenced (and specialized) by using the absolute path to it (/service_name/component_name/identity_nameThis does not override the component-level identity, it essentially creates a copy of it and updates the copy's properties. 

Component-level Configurations

Component-level configurations is an optional configurations block listing zero or more configuration descriptors that are specific to the component.

Component-level Auth-to-local-properties

Component-level auth-to-local-properties is an optional list of zero or more configuration property specifications (config-type/property_name[|concatenation_scheme]) indicating which properties contain auth-to-local rule sets and how to concatenate the rules to meet the property specifications. These sets are dynamically updated using the details from the identities used when Kerberizing the cluster and concatenated as indicated.  The concatenation scheme value is optional.

 If specified one of the following schemes must be specified: 

  • new_lines - rules in the rule set are separated by a new line (\n)
  • new_lines_escaped - rules in the rule set are separated by a \ and a new line (\ \n)
  • spaces - rules in the rule set are separated by a whitespace character (effectively placing all rules in a single line)

 If not specified, the default concatenation scheme is new_lines.

Examples

 Service site property using the default concatenation scheme

  core-site/hadoop.security.auth_to_local

 Service site property explicitly using the escaped new lines concatenation scheme

startup.properties/http.authentication.kerberos.name.rules|new_lines_escaped

Descriptor Specifications

properties

The properties descriptor is only valid in the service-level Kerberos Descriptor file. This block is a set of name/value pairs as follows:

"properties" : {
  "property_1" : "value_1",
  "property_2" : "value_2"
  ...
}

auth-to-local-properties

The auth-to-local-properties descriptor is valid in the stack-, service-, and component-level descriptors. This block is a list of configuration specifications (config-type/property_name[|concatenation_scheme]) indicating which properties contain auth-to-local rules that should be dynamically updated based on the identities used within the Kerberized cluster. The specification optionally declare the concatenation scheme to use to append the rules into a rule set value. 

"auth-to-local-properties" : [
  "core-site/hadoop.security.auth_to_local",
  "service.properties/http.authentication.kerberos.name.rules|new_lines_escaped",
  ...
]

configurations

A configurations descriptor may exist in stack-, service-, and component-level descriptors. This block is a list of one or more configuration descriptors, such that each descriptor is a block containing a single structure named using the configuration type and containing values for each relevant property.

Each property name and value may be a concrete value or contain variables to be replaced using values from the properties descriptor or any available configuration. Properties from the properties descriptor are referenced by name (${property_name}) and configuration properties are reference by configuration type followed by a forward slash (/) and then the property name (${config-type/property_name}).

"configurations" : [
  {
    "config-type-1" : {
      "${cluster-env/smokeuser}_property" : "value1", 
      "some_realm_property" : "${realm}",
 
      ...

    }
  },
  {
    "config-type-2" : {
      "property-2" : "${cluster-env/smokeuser}",
      ...
    }
  },
  ...

]

If "cluster-env/smokuser" was "ambari-qa" and realm was "EXAMPLE.COM", the above block would effectively be translated to

"configurations" : [
  {
    "config-type-1" : {
      "ambari-qa_property" : "value1", 
      "some_realm_property" : "EXAMPLE.COM",
 
     ...

    }
  },
  {
    "config-type-2" : {
      "property-2" : "ambari-qa",
      ...
    }
  },
  ...

]

identities

An identities descriptor may exist in stack-, service-, and component-level descriptors. This block is a list of zero or more identity descriptors. Each identity descriptor is a block containing a name, an optional principal descriptor, and an optional keytab descriptor.

The name property of an identity descriptor may be a concrete name or a reference to some other identity in the composite Kerberos Descriptor. If the name represents a reference (starts with a / or a ../) the reference will be “copied” to the local scope and any values in the local principal or keytab descriptor will be used to override the base values.

"identities" : [
  {
    "name" : "local_identity",
    "principal" : {
      ...
    },
    "keytab" : {
      ...
    }
  },
  {
    "name" : "/smokeuser",
    "principal" : {
      ...
    },
    "keytab" : {
      ...
    }
  },
  ...
]

principal

The principal descriptor is an optional block inside an identity descriptor. It declares the details about the identity’s principal including the principal’s value, the type (user or service), the relevant configuration property, and a local username mapping. All properties are optional; however if no base or default value is available for all properties, the principal may be ignored.

The value property of the principal is expected to be the normalized principal name, including the principal’s components and realm. In most cases, the realm should be specified using the realm variable (${realm} or ${kerberos-env/realm}). Also, in the case of a service principal, "_HOST" should be used to represent the relevant hostname, however the built-in hostname variable (${hostname}) may be used if "_HOST" replacement on the agent-side is not available for the service. For example, smokeuser@${realm}, service/_HOST@${realm}.

The type property of the principal may be either “user” or “service”. If not specified, the type is assumed to be “user”. This value dictates how the identity is to be created in the KDC or Active Directory. It is especially important in the Active Directory case due to how accounts are created.

The configuration property is an optional configuration specification (config-type/property_name) that is to be set to this principal's value property after it's variables have been replaced.  

The local_username property, if supplied, indicates which local user account to use when generating auth-to-local rules for this identity. If not specified, no explicit rule will be generated.

"principal" : {
  "value": "${cluster-env/smokeuser}@${realm}",
  "type" : "user" ,
  "configuration": "cluster-env/smokeuser_principal_name",
  "local_username" : "${cluster-env/smokeuser}"
}

"principal" : {
  "value": "component1/_HOST@${realm}",
  "type" : "service" ,
  "configuration": "service-site/component1.principal"
}

keytab

The keytab descriptor is an optional block inside an identity descriptor. It describes how to create and store the relevant keytab file.  This block declares the keytab file's path in the local filesystem, the permissions to assign to that file, and the relevant configuration property.

The file property declares an absolute path to use to store the keytab file when distributing to relevant hosts. If this is not supplied, the keytab file will not be created.

The owner property is an optional block indicating the local user account to assign as the owner of the file and what access  (“rw” - indicates read/write access; “r” - indicates read-only access) should be granted to that user. By default, the owner will be given read-only access.

The group property is an optional block indicating which local group to assigned as the group owner of the file and what access (“rw” - indicates read/write access; “r” - indicates read-only access. “” - indicates no access) should be granted to local user accounts in that group. By default, the group will be given no access.

The configuration property is an optional configuration specification (config-type/property_name) that is to be set to the path of this keytabs file, after any variables have been replaced.  

"keytab" : {
  "file": "${keytab_dir}/smokeuser.headless.keytab",
  "owner": {
    "name": "${cluster-env/smokeuser}",
    "access": "r"
  },
  "group": {
    "name": "${cluster-env/user_group}",
    "access": "r"
  },
  "configuration": "${cluster-env/smokeuser_keytab}"
}

services

A service descriptor may exist in the stack-level and the service-level Kerberos Descriptor file. This block is a list of zero or more service descriptors to add to the composite Kerberos Descriptor. Each service descriptor is a block containing a service name, an optional identities block, an optional auth_to_local_properties block, an optional configurations block, and an optional components block.

"services": [
  {
    "name": "SERVICE",
    "identities": [
      ...
    ],
    "auth_to_local_properties" : [
      ...
    ],
    "configurations": [
      ...
    ],
    "components": [
      ...
    ]
  },
  …
]

components

A component descriptor may exist in the service-level Kerberos Descriptor file. This block is a list of zero or more component descriptors belonging to the containing service descriptor. Each component descriptor is a block containing a component name, an optional identities block, an optional auth_to_local_properties block, and an optional configurations block.

"components": [
  {
    "name": "COMPONENT_NAME",
    "identities": [
      ...
    ],
    "auth_to_local_properties" : [
      ...
    ],
    "configurations": [
      ...
    ]
  },
  ...
]

Examples

Example Stack-level Kerberos Descriptor

The following example is annotated for descriptive purposes. The annotations are not valid in a real JSON-formatted file.

{
  // Properties that can be used in variable replacement operations. 
  // For example, ${keytab_dir} will resolve to "/etc/security/keytabs".
  // Since variable replacement is recursive, ${realm} will resolve 
  // to ${kerberos-env/realm}, which in-turn will resolve to the 
  // declared default realm for the cluster
  "properties": {
    "realm": "${kerberos-env/realm}",
    "keytab_dir": "/etc/security/keytabs"
  },
  // A list of global Kerberos identities. These may be referenced 
  // using /identity_name. For example the “spnego” identity may be 
  // referenced using “/spnego”
  "identities": [
    {
      "name": "spnego",
      // Details about this identity's principal. This instance does not
      // declare any value for configuration or local username. That is
      // left 
up to the services and components use wish to reference 
      // this principal and set overrides for those values.
      "principal": {
        "value": "HTTP/_HOST@${realm}",
        "type" : "service"
      },

      // Details about this identity’s keytab file. This keytab file 
      // will be created in the configured keytab file directory with 
      // read-only access granted to root and users in the cluster’s 
      // default user group (typically, hadoop). To ensure that only 
      // a single copy exists on the file system, references to this 
      // identity should not override the keytab file details; 
      // however if it is desired that multiple keytab files are 
      // created, these values may be overridden in a reference 
      // within a service or component. Since no configuration 
      // specification is set, the the keytab file location will not 
      // be set in any configuration file by default. Services and 
      // components need to reference this identity to update this
      // value as needed
.
      "keytab": {
        "file": "${keytab_dir}/spnego.service.keytab",
        "owner": {
          "name": "root",
          "access": "r"
        },
        "group": {
          "name": "${cluster-env/user_group}",
          "access": "r"
        }
      }
    },
    {
      "name": "smokeuser",
      // Details about this identity's principal. This instance declares
      // a configuration and local 
username mapping. Services and
      // components can override this t
o set additional configurations
      // that should be set to this 
principal value.  Overriding the
      // local username 
may create undesired behavior since there may be
      // conflicting 
entries in relevant auth-to-local rule sets.
      "principal": {
        "value": "${cluster-env/smokeuser}@${realm}",
        "type" : "user",
        "configuration": "cluster-env/smokeuser_principal_name",
        "local_username" : "${cluster-env/smokeuser}"
      },
      // Details about this identity’s keytab file. This keytab file 
      // will be created in the configured keytab file directory with 
      // read-only access granted to the configured smoke user 
      // (typically ambari-qa) and users in the cluster’s default 
      // user group (typically hadoop). To ensure that only a single 
      // copy exists on the file system, references to this identity 
      // should not override the keytab file details; however if it 
      // is desired that multiple keytab files are created, these 
      // values may be overridden in a reference within a service or 
      // component.
      "keytab": {
        "file": "${keytab_dir}/smokeuser.headless.keytab",
        "owner": {
          "name": "${cluster-env/smokeuser}",
          "access": "r"
        },
        "group": {
          "name": "${cluster-env/user_group}",
          "access": "r"
        },
        "configuration": "cluster-env/smokeuser_keytab"
      }
    }
  ]
}

Example Service-level Kerberos Descriptor

The following example is annotated for descriptive purposes. The annotations are not valid in a real JSON-formatted file.

{
  // One or more services may be listed in a service-level Kerberos
  // Descriptor file
  "services": [
    {
      "name": "SERVICE_1",
      // Service-level identities to be created if this service is installed.  
      // Any relevant keytab files will be distributed to hosts with at least
      // one of the components on it.

      "identities": [
        // Service-specific identity declaration, declaring all properties
        // needed initiate the creation of the principal and keytab files,
        // as well as setting the service-specific  configurations.  This may
        // be referenced by contained components using ../service1_identity.
        {
          "name": "service1_identity",
          "principal": {
            "value": "service1/_HOST@${realm}",
            "type" : "service",
  
          "configuration": "service1-site/service1.principal"

          },
          "keytab": {
            "file": "${keytab_dir}/service1.service.keytab",
            "owner": {
              "name": "${service1-env/service_user}",
              "access": "r"
            },
            "group": {
              "name": "${cluster-env/user_group}",
              "access": "r"
            },
  
          "configuration": "service1-site/service1.keytab.file"

          }
        },
        // Service-level identity referencing the stack-level spnego
        // identity and overriding the principal and keytab configuration
        // specifications.
        {
          "name": "/spnego",
          "principal": {
            "configuration": "service1-site/service1.web.principal"
          },
          "keytab": {
            "configuration": "service1-site/service1.web.keytab.file"
          }
        },
        // Service-level identity referencing the stack-level smokeuser 
        // identity. No properties are being overridden and overriding
        // the principal and keytab configuration 
specifications.
  
      {

          "name": "/smokeuser"
        }
      ],
      // Properties related to this service that require the auth-to-local
      // rules to be dynamically generated based on identities create for
      // the cluster.
      "auth_to_local_properties" : [
        "service1-site/security.auth_to_local"
      ],
      // Configuration properties to be set when this service is installed,
      // no matter which components are installed
      "configurations": [
        {
          "service-site": {
            "service1.security.authentication": "kerberos",
            "service1.security.auth_to_local": ""
          }
        }
      ],
      // A list of components related to this service
      "components": [

        {
          "name": "COMPONENT_1",
          // Component-specific identities to be created when this component
          // is installed.  Any keytab files specified will be distributed
          // only to the hosts where this component is installed.
          "identities": [

            // An identity "local" to this component
            {

              "name": "component1_service_identity",
              "principal": {
                "value": "component1/_HOST@${realm}",
                "type" : "service",
                "configuration": "service1-site/comp1.principal",
                "local_username" : "${service1-env/service_user}"
              },
              "keytab": {
                "file": "${keytab_dir}/s1c1.service.keytab",
                "owner": {
                  "name": "${service1-env/service_user}",
                  "access": "r"
                },
                "group": {
                  "name": "${cluster-env/user_group}",
                  "access": ""
                },
                "configuration": "service1-site/comp1.keytab.file"
              }
            },
            // The stack-level spnego identity overridden to set component-specific
            // configurations 

  
          {

              "name": "/spnego",
              "principal": {
                "configuration": "service1-site/comp1.spnego.principal"
              },
              "keytab": {
                "configuration": "service1-site/comp1.spnego.keytab.file"
              }  
          
            }

          ],
          // Component-specific configurations to set if this component is installed
          "configurations": [

            {
              "service-site": {
                "comp1.security.type": "kerberos"
              }
            }
          ]
        },
        {
          "name": "COMPONENT_2",
          "identities": [
            {
              "name": "component2_service_identity",
              "principal": {
                "value": "component2/_HOST@${realm}",
                "type" : "service",
                "configuration": "service1-site/comp2.principal",
                "local_username" : "${service1-env/service_user}"
              },
              "keytab": {
                "file": "${keytab_dir}/s1c2.service.keytab",
                "owner": {
                  "name": "${service1-env/service_user}",
                  "access": "r"
                },
                "group": {
                  "name": "${cluster-env/user_group}",
                  "access": ""
                },
                "configuration": "service1-site/comp2.keytab.file"
              }
            },
            // The service-level service1_identity identity overridden to
            // set component-specific configurations 

            {

              "name": "../service1_identity",
              "principal": {
                "configuration": "service1-site/comp2.service.principal"
              },
              "keytab": {
                "configuration": "service1-site/comp2.service.keytab.file"
              }            
            }

  
        ],

          "configurations" : [
            {
              "service-site" : {
                "comp2.security.type": "kerberos"
              }
            }
          ]
        }
      ]
    }
  ]
}

The Kerberos Service

Configurations

kerberos-env

kdc_type

The type of KDC being used. Either mit-kdc or active-directory

Possible Values: mit-kdc, active-directory 

manage_identities

Indicates whether the Ambari user and service Kerberos identities (principals and keytab files) should be managed (created, deleted, updated, etc...) by Ambari or managed manually.

Possible Values: true, false

install_packages

Indicates whether Ambari should install the Kerberos client package(s) or not. If not, it is expected that Kerberos utility programs (such as kadmin, kinit, klist, and kdestroy) are compatible with MIT Kerberos 5 version 1.10.3 in command line options and behaviors.

Possible Values: true, false

ldap_url

The URL to the Active Directory LDAP Interface. This value must indicate a secure channel using LDAPS since it is required for creating and updating passwords for Active Directory accounts. 

Example:  ldaps://ad.example.com:636

container_dn

The distinguished name (DN) of the container used store service principals

Example:  OU=hadoop,DC=example,DC=com

encryption_types

The supported (space-delimited) list of session key encryption types that should be returned by the KDC.

Default value: aes des3-cbc-sha1 rc4 des-cbc-md5

realm

The default realm to use when creating service principals

Example: EXAMPLE.COM

kdc_host (<Ambari 2.4.0)

The IP address or FQDN for the KDC host. Optionally a port number may be included.

Example:  kdc.example.com

Example: kdc.example.com:88

kdc_hosts (>=Ambari 2.4.0)

A comma-delimited list of IP addresses or FQDNs for the list of relevant KDC hosts. Optionally a port number may be included for each entry.

Example:  kdc.example.com, kdc1.example.com

Example: kdc.example.com:88, kdc1.example.com:88 

admin_server_host

The IP address or FQDN for the KDC Kerberos administrative host. Optionally a port number may be included.

Example: kadmin.example.com

Example: kadmin.example.com:88 

executable_search_paths

A comma-delimited list of search paths to use to find Kerberos utilities like kadmin and kinit.

Default value: /usr/bin, /usr/kerberos/bin, /usr/sbin, /usr/lib/mit/bin, /usr/lib/mit/sbin

password_length

The length required length for generated passwords.

Default value: 20

password_min_lowercase_letters

The minimum number of lowercase letters (a-z) required in generated passwords

Default value: 1

password_min_uppercase_letters

The minimum number of uppercase letters (A-Z) required in generated passwords

Default value: 1

password_min_digits

The minimum number of digits (0-9) required in generated passwords

Default value: 1

password_min_punctuation

The minimum number of punctuation characters (?.!$%^*()-_+=~) required in generated passwords

Default value: 1

password_min_whitespace

The minimum number of whitespace characters required in generated passwords

Default value: 0

service_check_principal_name

The principal name to use when executing the Kerberos service check

Example: ${cluster_name}-${short_date}

case_insensitive_username_rules

Force principal names to resolve to lowercase local usernames in auth-to-local rules

Possible values: true, false

Default value: false

ad_create_attributes_template

A Velocity template to use to generate a JSON-formatted document containing the set of attribute names and values needed to create a new Kerberos identity in the relevant Active Directory.

Variables include: principal_name, principal_primary, principal_instance, realm, realm_lowercase, normalized_principal, principal digest, password, is_service, container_dn

Note: This is used only in the case when the kdc-type is active-directory.

Default value:
{
"objectClass": ["top", "person", "organizationalPerson", "user"],
"cn": "$principal_name",
#if( $is_service )
"servicePrincipalName": "$principal_name",
#end
"userPrincipalName": "$normalized_principal",
"unicodePwd": "$password",
"accountExpires": "0",
"userAccountControl": "66048"
}

kdc_create_attributes

The set of attributes to use when creating a new Kerberos identity in the relevant (MIT) KDC.

Note: This is used only in the case when the kdc-type is mit-kdc.

Example: -requires_preauth max_renew_life=7d

krb5-conf

manage_krb5_conf

Indicates whether your krb5.conf file should be managed by the wizard or should you manage it yourself

Possible values: true, false

Default value: false

domains

A comma-separated list of domain names used to map server host names to the Realm name (e.g. .example.com,example.com). This is optional.

Example: host.example.com, example.com, .example.com

conf_dir

The krb5.conf configuration directory

Default value: /etc

content

Customizable krb5.conf template (Jinja template engine)

Example: [libdefaults]

renew_lifetime = 7d
forwardable = true
default_realm = {{realm}}
ticket_lifetime = 24h
dns_lookup_realm = false
dns_lookup_kdc = false
#default_tgs_enctypes = {{encryption_types}}
#default_tkt_enctypes = {{encryption_types}}

{% if domains %}
[domain_realm]
{% for domain in domains.split(',') %}
{{domain}} = {{realm}}
{% endfor %}
{% endif %}

[logging]
default = FILE:/var/log/krb5kdc.log

admin_server = FILE:/var/log/kadmind.log
kdc = FILE:/var/log/krb5kdc.log

[realms]
{{realm}} = {

  admin_server = {{admin_server_host|default(kdc_host, True)}}
  kdc = {{kdc_host}}

}

{# Append additional realm declarations below #}

Enabling Kerberos

Enabling Kerberos on the cluster may be done using the Enable Kerberos Wizard within the Ambari UI or using the REST API.  

The Enable Kerberos Wizard (Ambari UI)

The Enable Kerberos Wizard provides an easy to use wizard interface that walks through the process of enabling Kerberos.  

The REST API

It is possible to enable Kerberos using Ambari's REST API using the following API calls:

Notes:

  • Change the authentication credentials as needed
    • curl ... -u username:password ...
    • The examples below use 
      • username: admin
      • password: admin
  • Change the Ambari server host name and port as needed
    • curl ... http://HOST:PORT/api/v1/...
    • The example below use
      • HOST:  AMBERI_SERVER
      • PORT: 8080
  • Change the cluster name as needed
    • curl ... http://.../CLUSTER/...
    • The example below use
      • CLUSTER:  CLUSTER_NAME
  • @./payload indicates the the payload data is stored in some file rather than declared inline 
    • curl ... -d @./payload ...
    • The examples below use ./payload which should be replace with the actual file path
    • The contents of the payload file are indicated below the curl statement

Add the KERBEROS Service to cluster

curl -H "X-Requested-By:ambari" -u admin:admin -i -X POST http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/services/KERBEROS

Add the KERBEROS_CLIENT component to the KERBEROS service

curl -H "X-Requested-By:ambari" -u admin:admin -i -X POST http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/services/KERBEROS/components/KERBEROS_CLIENT

Create and set KERBEROS service configurations

curl -H "X-Requested-By:ambari" -u admin:admin -i -X PUT -d @./payload http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME

Payload when using an MIT KDC

[
  {
    "Clusters": {
      "desired_config": {
        "type": "krb5-conf",
        "tag": "version1",
        "properties": {
          "domains":"",
          "manage_krb5_conf": "true",
          "conf_dir":"/etc",
          "content" : "[libdefaults]\n  renew_lifetime = 7d\n  forwardable= true\n  default_realm = {{realm|upper()}}\n  ticket_lifetime = 24h\n  dns_lookup_realm = false\n  dns_lookup_kdc = false\n  #default_tgs_enctypes = {{encryption_types}}\n  #default_tkt_enctypes ={{encryption_types}}\n\n{% if domains %}\n[domain_realm]\n{% for domain in domains.split(',') %}\n  {{domain}} = {{realm|upper()}}\n{% endfor %}\n{%endif %}\n\n[logging]\n  default = FILE:/var/log/krb5kdc.log\nadmin_server = FILE:/var/log/kadmind.log\n  kdc = FILE:/var/log/krb5kdc.log\n\n[realms]\n  {{realm}} = {\n    admin_server = {{admin_server_host|default(kdc_host, True)}}\n    kdc = {{kdc_host}}\n }\n\n{# Append additional realm declarations below #}\n"
        }
      }
    }
  },
  {
    "Clusters": {
      "desired_config": {
        "type": "kerberos-env",
        "tag": "version1",
        "properties": {
          "kdc_type": "mit-kdc",
          "manage_identities": "true",
          "install_packages": "true",
          "encryption_types": "aes des3-cbc-sha1 rc4 des-cbc-md5",
          "realm" : "EXAMPLE.COM",
          "kdc_host" : "KDC_SERVER",
          "admin_server_host" : "KDC_SERVER",
          "executable_search_paths" : "/usr/bin, /usr/kerberos/bin, /usr/sbin, /usr/lib/mit/bin, /usr/lib/mit/sbin",
          "password_length": "20",
          "password_min_lowercase_letters": "1",
          "password_min_uppercase_letters": "1",
          "password_min_digits": "1",
          "password_min_punctuation": "1",
          "password_min_whitespace": "0",
          "service_check_principal_name" : "${cluster_name}-${short_date}",
          "case_insensitive_username_rules" : "false"

        }

      }
    }
  }
]

Payload when using an Active Directory

[
  {
    "Clusters": {
      "desired_config": {
        "type": "krb5-conf",
        "tag": "version1",
        "properties": {
          "domains":"",
          "manage_krb5_conf": "true",
          "conf_dir":"/etc",
          "content" : "[libdefaults]\n  renew_lifetime = 7d\n  forwardable= true\n  default_realm = {{realm|upper()}}\n  ticket_lifetime = 24h\n  dns_lookup_realm = false\n  dns_lookup_kdc = false\n  #default_tgs_enctypes = {{encryption_types}}\n  #default_tkt_enctypes ={{encryption_types}}\n\n{% if domains %}\n[domain_realm]\n{% for domain in domains.split(',') %}\n  {{domain}} = {{realm|upper()}}\n{% endfor %}\n{%endif %}\n\n[logging]\n  default = FILE:/var/log/krb5kdc.log\nadmin_server = FILE:/var/log/kadmind.log\n  kdc = FILE:/var/log/krb5kdc.log\n\n[realms]\n  {{realm}} = {\n    admin_server = {{admin_server_host|default(kdc_host, True)}}\n    kdc = {{kdc_host}}\n }\n\n{# Append additional realm declarations below #}\n"
        }
      }
    }
  },
  {
    "Clusters": {
      "desired_config": {
        "type": "kerberos-env",
        "tag": "version1",
        "properties": {
          "kdc_type": "active-directory",
          "manage_identities": "true",
          "install_packages": "true",
          "encryption_types": "aes des3-cbc-sha1 rc4 des-cbc-md5",
          "realm" : "EXAMPLE.COM",
          "kdc_host" : "AD_HOST",
          "admin_server_host" : "AD_HOST",
          "ldap_url" : "LDAPS://AD_HOST:PORT",
          "container_dn" : "OU=....,....",
          "executable_search_paths" : "/usr/bin, /usr/kerberos/bin, /usr/sbin, /usr/lib/mit/bin, /usr/lib/mit/sbin",
          "password_length": "20",

          "password_min_lowercase_letters": "1",
          "password_min_uppercase_letters": "1",
          "password_min_digits": "1",
          "password_min_punctuation": "1",
          "password_min_whitespace": "0",
          "service_check_principal_name" : "${cluster_name}-${short_date}",
          "case_insensitive_username_rules" : "false",
          "create_attributes_template" :  "{\n \"objectClass\": [\"top\", \"person\", \"organizationalPerson\", \"user\"],\n \"cn\": \"$principal_name\",\n #if( $is_service )\n \"servicePrincipalName\": \"$principal_name\",\n #end\n \"userPrincipalName\": \"$normalized_principal\",\n \"unicodePwd\": \"$password\",\n \"accountExpires\": \"0\",\n \"userAccountControl\": \"66048\"}"
        }

      }
    }
  }
]

Create the KERBEROS_CLIENT host components (once for each host, replace HOST_NAME)

curl -H "X-Requested-By:ambari" -u admin:admin -i -X POST -d '{"host_components" : [{"HostRoles" : {"component_name":"KERBEROS_CLIENT"}}]}' http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/hosts?Hosts/host_name=HOST_NAME

Install the KERBEROS service and components

curl -H "X-Requested-By:ambari" -u admin:admin -i -X PUT -d '{"ServiceInfo": {"state" : "INSTALLED"}}' http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/services/KERBEROS

Stop all services

curl -H "X-Requested-By:ambari" -u admin:admin -i -X PUT -d  '{"RequestInfo":{"context":"Stop Service"},"Body":{"ServiceInfo":{"state":"INSTALLED"}}}' http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/services

Get the default Kerberos Descriptor

curl -H "X-Requested-By:ambari" -u admin:admin -i -X GET http://AMBARI_SERVER:8080/api/v1/stacks/STACK_NAME/versions/STACK_VERSION/artifacts/kerberos_descriptor

Get the customized Kerberos Descriptor (if previously set)

curl -H "X-Requested-By:ambari" -u admin:admin -i -X GET http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/artifacts/kerberos_descriptor

Set the Kerberos Descriptor

curl -H "X-Requested-By:ambari" -u admin:admin -i -X POST -d @./payload http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/artifacts/kerberos_descriptor

Payload

The Kerberos Descriptor payload may be a complete Kerberos Descriptor or just the updates to overlay on top of the default Kerberos Descriptor.  

Enable Kerberos

curl -H "X-Requested-By:ambari" -u admin:admin -i -X PUT -d @./payload http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME

Payload

{
  "session_attributes" : {

    "kerberos_admin" : {
      "principal" : "ADMIN_PRINCIPAL",
      "password" : "ADMIN_PASSWORD"
    }
  },
  "Clusters": {
    "security_type" : "KERBEROS"
  }
}

Start all services

curl -H "X-Requested-By:ambari" -u admin:admin -i -X PUT -d '{"ServiceInfo": {"state" : "STARTED"}}' http://AMBARI_SERVER:8080/api/v1/clusters/CLUSTER_NAME/services

Technical Information

Password Generation

When Ambari generates keytab files, it uses an internal mechanism rather than rely on the KDC or Active Directory to do it.  This is mainly because Ambari cannot request a keytab file from an Active Directory. Because of this, Ambari needs to know the password for each Kerberos identity that needs a keytab file created and thus it sets or updates the identity's password a needed. 

The password for each Ambari-managed account in a KDC or Active Directory is randomly generated and stored only long enough to set the account's password and generate the keytab file. 

Ambari 2.0.x

Generated passwords in Ambari 2.0.x meet the following specifications

Ambari 2.1.x (and above)

Passwords in Ambari 2.1.x (and above) are generated using the following user-settable parameters:

  • Password length (kerberos-env/password_length), default 20
  • Minimum number of lower-cased letters (kerberos-env/password_min_lowercase_letters), default 1
    • Set: abcdefghijklmnopqrstuvwxyz
  • Minimum number of upper-cased letters (kerberos-env/password_min_uppercase_letters), default 1
    • Set: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • Minimum number of digits (kerberos-env/password_min_digits), default 1 
    • Set: 1234567890
  • Minimum number of punctuation characters (kerberos-env/password_min_punctuation), default 1
    • Set: ?.!$%^*()-_+=~ 
  • Minimum number of whitespace characters (kerberos-env/password_min_whitespace), default 0
    • Set: (space character)

The following algorithm is executed:

  • Create an array to store password characters
  • For each character class (upper-case letter, lower-case letter, digit, ...), randomly select from the relevant set the minimum number of characters and store them in the array
  • For the number of characters calculated as the difference between the expected password length and the number of characters already collected, randomly select a character from a randomly-selected character class and store into the array
  • For the number of characters expected in the password, randomly pull one from the array and append to the password result
  • Return the generated password

To generate a random integer used to identify an index within a character set,  static instance of the java.security.SecureRandom class (see http://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html) is used.


(more to come...)

  • No labels