RJ Systems
Linux System Administration
Home Tech Linux Links Consulting

Valid XHTML 1.0!

Valid CSS!

IPv6 test

Integrated Kerberos-OpenLDAP-OpenAFS provider


This page describes how to set up an initial OpenAFS file server, an OpenLDAP provider server and an MIT Kerberos V master server, all on the same host, with Kerberos using OpenLDAP as a back-end for its database. Often referred to as the magic trio, when combined they form an enormously scalable open source network operating system that offers unequaled file system availability, excellent security and encryption, and a directory service for centralized management of access to workstations, servers, printers and other resources that are part of the same network.

In this example, everything is installed on a single host running Debian 5.0 (lenny). If followed properly, the step-by-step process should first produce an OpenLDAP provider server with a new Directory Information Tree (DIT), followed by a Kerberos master server that stores its database in the same DIT, and finally an OpenAFS file server with a new AFS cell. The system relies heavily on timestamps, so reasonably accurate time synchronization among all participating hosts is essential.

However, before the interesting parts can begin, it will first be necessary to install the operating system on a new host called klas1.example.com. A DNS server must also be available on the network with a zone file to which forward and reverse mappings can be added for this host, as well as an alias for it called klas.example.com. After the initial installation of the operating system, make sure these packages are installed on the system as well:

~# apt-get install ssh ntp ntpdate nmap

Afterwards, edit /etc/ntp.conf so that the machine synchronizes to a common NTP server (preferably a local one) and edit /etc/default/ntpdate to use the same host also. Now the installation of the new Kerberos-LDAP-AFS provider server can begin.

1. OpenLDAP install

On the new host, klas1.example.com, start by installing these two packages:

~# apt-get install slapd ldap-utils

A total of ten packages are installed as a result, including eight dependencies:

ldap-utils                 2.4.11-1+lenny1             OpenLDAP utilities
libdb4.2                   4.2.52+dfsg-5               Berkeley v4.2 Database Libraries [runtime]
libltdl3                   1.5.26-4+lenny1             A system independent dlopen wrapper for GNU libtool
libperl5.10                5.10.0-19lenny2             Shared Perl library
libsasl2-modules           2.1.22.dfsg1-23+lenny1      Cyrus SASL - pluggable authentication modules
libslp1                    1.2.1-7.5                   OpenSLP libraries
odbcinst1debian1           2.2.11-16                   Support library and helper program for accessing odbc ini file
psmisc                     22.6-1                      Utilities that use the proc filesystem
slapd                      2.4.11-1+lenny1             OpenLDAP server (slapd)
unixodbc                   2.2.11-16                   ODBC tools libraries

During the install process, an administrator password will be requested for slapd. Use cerastes:

Administrator password: cerastes
Confirm password: cerastes

Run the following command to test if the OpenLDAP server is actually running:

~# nmap klas1.example.com

This should be among the results:

389/tcp open  ldap

Perform a quick test by generating an LDIF dump of the contents of a the database:

~# slapcat
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: fc3a2af0-bb32-102e-9fff-e39e39be5fd5
createTimestamp: 20100303170725Z
entryCSN: 20100303170725.811639Z#000000#000#000000
modifyTimestamp: 20100303170725Z

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e2NyeXB0fURvQUhUWGR3WUIzZDY=
structuralObjectClass: organizationalRole
entryUUID: fc3b90a2-bb32-102e-8000-e39e39be5fd5
createTimestamp: 20100303170725Z
entryCSN: 20100303170725.821117Z#000000#000#000000
modifyTimestamp: 20100303170725Z

~# _

2. ldap.conf

Edit /etc/ldap/ldap.conf and use these two lines:

BASE    dc=example,dc=com
URI     ldap://klas1.example.com/

This configuration file is used to set system-wide defaults for LDAP clients.

3. Basic tree

Create a basic tree structure. First create a file, ~/basic-tree.ldif, with the following content:

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

dn: ou=hosts,dc=example,dc=com
objectClass: organizationalUnit
ou: hosts

Add this information to the LDAP database using the ldapadd command:

~# ldapadd -xWD cn=admin,dc=example,dc=com -f ~/basic-tree.ldif
Enter LDAP Password: cerastes
adding new entry "ou=people,dc=example,dc=com"

adding new entry "ou=groups,dc=example,dc=com"

adding new entry "ou=hosts,dc=example,dc=com"

~# _

A quick ldapsearch should show the new objects:

~# ldapsearch -xLLL
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

dn: ou=hosts,dc=example,dc=com
objectClass: organizationalUnit
ou: hosts


4. Kerberos master install

On the new host, klas1.example.com, start by installing these three packages:

~# apt-get install krb5-{admin-server,kdc-ldap,user}

A total of six packages are installed as a result, including three dependencies:

krb5-admin-server          1.6.dfsg.4~beta1-5lenny2             MIT Kerberos master server (kadmind)
krb5-config                1.22                                 Configuration files for Kerberos Version 5
krb5-kdc                   1.6.dfsg.4~beta1-5lenny2             MIT Kerberos key server (KDC)
krb5-kdc-ldap              1.6.dfsg.4~beta1-5lenny2             MIT Kerberos key server (KDC) LDAP plugin
krb5-user                  1.6.dfsg.4~beta1-5lenny2             Basic programs to authenticate using MIT Kerberos
libkadm55                  1.6.dfsg.4~beta1-5lenny2             MIT Kerberos administration runtime libraries

During package installation, the default realm is automatically set to EXAMPLE.COM. A few questions are asked regarding the krb5-admin-server package that should be answered as follows:

Kerberos servers for your realm: klas1.example.com
Administrative server for your Kerberos realm: klas.example.com

Following this automated configuration sequence for the package, one problem appears: kadmind, the administration daemon, has failed to start. This is because the realm, EXAMPLE.COM, or rather a database for it, has not yet been created; an issue that will be addressed later on.

Since the idea is for Kerberos to use OpenLDAP as its back-end database, see to it that the Kerberos KDC and administrative services start up after slapd by changing the names of the symbolic links for their respective startup scripts:

~# mv /etc/rc2.d/S18krb5-kdc /etc/rc2.d/S20krb5-kdc
~# mv /etc/rc2.d/S18krb5-admin-server /etc/rc2.d/S20krb5-admin-server
~# _

5. Admin authorization

Edit /etc/krb5kdc/kadm5.acl and enable/add the following two lines:

*/admin *
admin *

This is to allow certain principals, admin and names ending in /admin, to perform any operation.

6. krb524d bug

This version of Kerberos includes the V to IV ticket conversion daemon, krb524d. Unfortunately, it suffers from a type of bug, called a file descriptor leak, that manifests itself when running Kerberos together with an LDAP back-end. The bug causes slapd to slowly run out of file descriptors and eventually become unresponsive. Since it is unlikely that the Kerberos developers will address this problem (krb524d has been removed from current Kerberos V releases), a workaround is necessary. Create a file, called /usr/local/bin/slapd-check, with the following contents:



openfiles=`lsof |grep -c slapd` 

daemonactive=`ps ax |grep -c krb524d`

if [ $daemonactive -gt 0 ] && [ $openfiles -gt 100 ]; then

        killall krb524d
        krb524d -m

exit 0

This script checks if krb524d is running, and if so, whether the number of files that slapd has open is greater than 100. If both these tests are true, only krb524d is killed and restarted.

Make the new script executable:

~# chmod 750 /usr/local/bin/slapd-check

Finally, have cron (crontab -e) run this script every fifteen minutes:

*/15 * * * * /usr/local/bin/slapd-check

7. slapd.conf

Unzip and copy the Kerberos schema file to the OpenLDAP server's schema directory:

~# gunzip -c /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz > \

Edit /etc/ldap/slapd.conf and make a number of changes to it. Starting at the top of the file, add a line to include support for the Kerberos schema in the DIT:

# Schema and objectClass definitions
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
include         /etc/ldap/schema/kerberos.schema

Comment out the logging option, which will return it to its default value (256):

#loglevel "none"

Later on, after the configuration is finished and the whole system is working properly, it will likely be desirable to once again return the loglevel value to "none", because Kerberos tends to cause a lot of slapd log output (at least once every minute) as it accesses its back-end database. This level of logging may also affect performance.

Add these two index directives for the uid and krb5principalname attributes:

index           objectClass eq
index           uid eq
index           krbPrincipalName eq,pres,sub

The first eq index will facilitate searches for uid entries, while the second will do the same for Kerberos principal entries. Both will speed up the login process.

Last, replace all of the existing ACLs with these:

access to attrs=userPassword,shadowLastChange
        by dn="cn=admin,dc=example,dc=com" write
        by anonymous auth
        by * none

access to dn.subtree="ou=krb5,dc=example,dc=com"
        by dn="cn=admin,dc=example,dc=com" write
	by dn="cn=adm-srv,ou=krb5,dc=example,dc=com" write
	by dn="cn=kdc-srv,ou=krb5,dc=example,dc=com" read
	by * none

access to attrs=loginShell
	by dn="cn=admin,dc=example,dc=com" write
        by self write
	by users read
        by * none

access to dn.base=""
	by * read

access to *
	by dn="cn=admin,dc=example,dc=com" write
	by users read
	by * none

Edit /etc/default/slapd and allow the LDAP service to listen for IPC connections (Unix domain sockets) by adding this line to the end of the file:

SLAPD_SERVICES="ldap:/// ldapi:///"

This will instruct slapd to listen on IPC, instead of only TCP port 389, which is the default.

Having saved these changes, restart the LDAP service:

~# /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.
~# _

8. krb5.conf

Edit the Kerberos realm configuration file, /etc/krb5.conf. This file is initially created by the Debian installer and contains information about the realms of a number of famous institutions, but none of that is necessary in this case. Instead, replace its contents with this:

	default_realm = EXAMPLE.COM
	forwardable = true
	proxiable = true

		kdc = klas1.example.com
		admin_server = klas.example.com
		database_module = openldap_ldapconf

	.example.com = EXAMPLE.COM
	example.com = EXAMPLE.COM

	ldap_kerberos_container_dn = ou=krb5,dc=example,dc=com

	openldap_ldapconf = {
		db_library = kldap
		ldap_kdc_dn = cn=kdc-srv,ou=krb5,dc=example,dc=com
		ldap_kadmind_dn = cn=adm-srv,ou=krb5,dc=example,dc=com
		ldap_service_password_file = /etc/krb5kdc/service.keyfile
		ldap_conns_per_server = 5

	kdc = FILE:/var/log/krb5/kdc.log
	admin_server = FILE:/var/log/krb5/kadmin.log
	default = FILE:/var/log/krb5/kadmin.log

See this section for a more detailed explanation of this file.

Note the absence of the ldap_servers statement from the list of openldap_ldapconf options. This is possible because the Kerberos daemons use IPC to connect to the LDAP back-end by default, while slapd was configured to support IPC in the previous step.

After /etc/krb5.conf has been saved, create the Kerberos log directory:

~# mkdir /var/log/krb5
~# _

To prevent the log files from growing too large, create a pair of logrotate configuration files. First, edit /etc/logrotate.d/krb5-kdc and give it the following contents:

/var/log/krb5/kdc.log {
	rotate 7
		/etc/init.d/krb5-kdc restart > /dev/null

Then edit /etc/logrotate.d/krb5-kadmin and give it this slightly different configuration:

/var/log/krb5/kadmin.log {
	rotate 7
		/etc/init.d/krb5-admin-server restart > /dev/null

9. Realm subtree

Create the entries mentioned in the /etc/krb5.conf file that will support the new Kerberos server. First create a file, ~/krb5.ldif, with the following contents:

dn: ou=krb5,dc=example,dc=com
ou: krb5
objectClass: organizationalUnit

dn: cn=kdc-srv,ou=krb5,dc=example,dc=com
cn: kdc-srv
objectClass: simpleSecurityObject
objectClass: organizationalRole
description: Default bind DN for the Kerberos KDC server
userPassword: polystictus

dn: cn=adm-srv,ou=krb5,dc=example,dc=com
cn: adm-srv
objectClass: simpleSecurityObject
objectClass: organizationalRole
description: Default bind DN for the Kerberos Administration server
userPassword: pusillus

Although the last two of these entries require only simple authentication (clear-text passwords), this is not an issue because, as opposed to using the network, only IPC will be used during the authentication of these accounts. After saving ~/krb5.ldif, add the new objects to the DIT with this command:

~# ldapadd -xWD cn=admin,dc=example,dc=com -f ~/krb5.ldif
Enter LDAP Password: cerastes
adding new entry "ou=krb5,dc=example,dc=com"

adding new entry "cn=kdc-srv,ou=krb5,dc=example,dc=com"

adding new entry "cn=adm-srv,ou=krb5,dc=example,dc=com"

~# _

10. Realm creation

To create the new realm, as opposed to the krb5_newrealm command, use kdb5_ldap_util:

~# kdb5_ldap_util -D cn=admin,dc=example,dc=com \
   -H ldap://klas1.example.com create -r EXAMPLE.COM -s
Password for "cn=admin,dc=example,dc=com": cerastes
Initializing database for realm 'EXAMPLE.COM'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key: oreganus
Re-enter KDC database master key to verify: oreganus
~# _

Use the slapcat command to verify the creation of the new database.

Passwords are needed for the two Kerberos services to access the Kerberos database in LDAP DIT. These passwords will be stashed in a file called /etc/krb5kdc/service.keyfile. First, create the stash for the KDC service, represented by the cn=kdc-srv object and referred to in /etc/krb5.conf with the ldap_kdc_dn option:

~# kdb5_ldap_util -D cn=admin,dc=example,dc=com stashsrvpw \
   -f /etc/krb5kdc/service.keyfile cn=kdc-srv,ou=krb5,dc=example,dc=com
Password for "cn=admin,dc=example,dc=com": cerastes
Password for "cn=kdc-srv,ou=krb5,dc=example,dc=com": polystictus
Re-enter password for "cn=kdc-srv,ou=krb5,dc=example,dc=com": polystictus
~# _

Then create a stash for the Kerberos administration server, represented by the cn=adm-srv object and referred to in /etc/krb5.conf with the ldap_kadmind_dn option:

~# kdb5_ldap_util -D cn=admin,dc=example,dc=com stashsrvpw \
   -f /etc/krb5kdc/service.keyfile cn=adm-srv,ou=krb5,dc=example,dc=com
Password for "cn=admin,dc=example,dc=com": cerastes
Password for "cn=adm-srv,ou=krb5,dc=example,dc=com": pusillus
Re-enter password for "cn=adm-srv,ou=krb5,dc=example,dc=com": pusillus
~# _

11. Admin user

Start up the local administrative interface for the new Kerberos database and create a principal for the admin user:

~# kadmin.local
Authenticating as principal root/admin@EXAMPLE.COM with password.
kadmin.local:  addprinc admin
WARNING: no policy specified for admin@EXAMPLE.COM; defaulting to no policy
Enter password for principal "admin@EXAMPLE.COM": cerastes
Re-enter password for principal "admin@EXAMPLE.COM": cerastes
Principal "admin@EXAMPLE.COM" created.
kadmin.local:  _

12. Ticket lifetime

Still in the local Kerberos administrative interface, use it now to allow more flexible lifetime and renewal time frames for the ticket granting ticket (TGT) service. The commands and their responses should look like this:

kadmin.local:  modprinc -maxlife "1 day" -maxrenewlife "90 day" \
Principal "krbtgt/EXAMPLE.COM@EXAMPLE.COM" modified.
kadmin.local:  q
~# _

The values entered above are instead of 10 hours and 1 day respectively, which are the default values. However, every organization should use values that best suit their own security needs. As for kadmin.local, this is a fail-safe version of the kadmin tool that can only be used on the KDC as root and requires no password to modify the database directly. The kadmin tool, on the other hand, can be used from anywhere on the network.

Now edit /etc/krb5kdc/kdc.conf and modify these two lines to reflect the changes made above:

        max_life = 1d 0h 0m 0s
        max_renewable_life = 90d 0h 0m 0s

13. Kerberos server start

Start the Kerberos admin and KDC servers for the first time:

~# /etc/init.d/krb5-admin-server start ; /etc/init.d/krb5-kdc start
~# _

If there are no errors, run the following command to verify that the new MIT Kerberos V master server is indeed available on the network:

~# nmap -sT -sU klas1.example.com.

Note the trailing dot! This should be among the results:

749/tcp  open          kerberos-adm
88/udp   open|filtered kerberos-sec
464/udp  open          kpasswd5
750/udp  open|filtered kerberos
4444/udp open|filtered krb524

14. Service princ & keytab

Use kadmin to create a Kerberos principal for the LDAP service and a matching keytab file by issuing a few commands:

(If a line exists in /etc/hosts that maps a loopback address to the FQDN, which in this case is klas1.example.com, it can prevent kadmin from starting up. If this line exists, remove it.)

~# kadmin -p admin
Authenticating as principal admin with password.
Password for admin@EXAMPLE.COM: cerastes
kadmin:  addprinc -randkey ldap/klas1.example.com
WARNING: no policy specified for ldap/klas1.example.com@EXAMPLE.COM;
defaulting to no policy
Principal "ldap/klas1.example.com@EXAMPLE.COM" created.
kadmin:  ktadd ldap/klas1.example.com
Entry for principal ldap/klas1.example.com with kvno 3, encryption type
AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab
Entry for principal ldap/klas1.example.com with kvno 3, encryption type
ArcFour with HMAC/md5 added to keytab
Entry for principal ldap/klas1.example.com with kvno 3, encryption type
Triple DES cbc mode with HMAC/sha1 added to keytab
Entry for principal ldap/klas1.example.com with kvno 3, encryption type
DES cbc mode with CRC-32 added to keytab
kadmin:  q
~# _

The -randkey switch is used because a machine cannot enter a password. To list the keys in /etc/krb5.keytab, use the klist -ke command. A host (or service) principal and a keytab file should be created for and saved on all of the various client machines that are part of a Kerberos realm.

15. Slapd kerberization

To kerberize slapd, start by installing this package:

~# apt-get install libsasl2-modules-gssapi-mit

Only one package is installed as a result:

libsasl2-modules-gssapi-mit      2.1.22.dfsg1-23+lenny1      Cyrus SASL - pluggable authentication modules (GSSAPI)

GSSAPI stands for Generic Security Service API. Defined in RFC-2743, it provides a common interface for accessing different security services, one of the most popular of which is Kerberos V. The way that GSSAPI services can be used for SASL authentication and the establishment of a security layer is described in RFC-2222 (Simple Authentication and Security Layer).

Change the permissions and ownership of the Kerberos keytab file to make sure that slapd can access it:

~# chmod 640 /etc/krb5.keytab
~# chown root.openldap /etc/krb5.keytab
~# _

Edit /etc/default/slapd and uncomment a line near the end of the file that will export the location of the Kerberos system keytab file as a variable:

export KRB5_KTNAME=/etc/krb5.keytab

Edit /etc/ldap/ldap.conf and add the following line to the end of the file to specify the authentication mechanism:


Now to configure the link that maps GSSAPI-format user names to LDAP names. Once users have been authenticated by Kerberos and have valid Kerberos tickets, the SASL layer redirects them to the GSSAPI mechanism. This results in distinguished names that consist of four parts:

  1. uid=user_name
  2. cn=realm_name
  3. cn=gssapi
  4. cn=auth

For instance, the Kerberos admin account becomes cn=admin,cn=example.com,cn=gssapi,cn=auth. The key is to match these GSSAPI-format names to ones that can be used together with the LDAP DIT. This is done by adding one or more authz-regexp directives to /etc/ldap/slapd.conf, which includes regular expressions. Modify this file by adding three such directives to the end of the Global directives section:

tool-threads 1




The three authz-regexp directives shown here are each followed by two options: a search pattern that matches one or more of the GSSAPI-format user names from the Kerberos database, and a replacement pattern that changes each name to a format that is compatible with the DIT, usually with the intention to match an existing LDAP entry.

The first of these authz-regexp directives is a specific match for the admin user, the second one matches names that begin with "host/" and changes them to DNs found in ou=hosts, while the third matches all other names and changes them to DNs found in ou=people. These are all examples of direct mapping, which is the generally recommended approach; it not only avoids the expense of searching for user DNs, but also allows mapping to DNs that do not have matching LDAP entries.

The drawback of direct mapping is that it only maps to a single organizational unit. To map to more than one organizational unit, use authz-regexp statements with LDAP URLs, which are referred to as search-based mappings. For instance, consider this stanza:


Note that, unlike the format used here for the sake of clarity, LDAP search URLs must always be written on a single line and without any of the extra spacing! In this example, the search pattern matches all GSSAPI-format names as before, but the replacement pattern searches two organizational units, people and robots, for matching LDAP user names. Unfortunately, this flexibility comes at a price, since it is slower than direct mapping, and it will not map GSSAPI names if no matching LDAP counterparts are found.

Anyway, still editing /etc/ldap/slapd.conf, add this directive, which specifies the Kerberos realm, to the end of the Global section, just below the last authz-regexp statement:


sasl-realm EXAMPLE.COM

This is important, because without it the authz-regexp mechanism will not work.

Having saved the above changes, restart the LDAP service:

~# /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.
~# _

16. Authentication test

Run some tests. First try a simple unauthenticated (-x) LDAP query:

~# ldapsearch -xLLL ou=people
No such object (32)
~# _

This does not work, because the default ACL has been set to "allow access to * by none" in slapd.conf. The authenticated version of this query, which is its default operational mode, will also give an error:

~# ldapsearch -LLL ou=people
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
~# _

The solution is to first acquire a Kerberos ticket for the admin user (password cerastes):

~# kinit admin
Password for admin@EXAMPLE.COM: cerastes
~# _

A verification of the ticket should show a success:

~# klist -5
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE.COM

Valid starting     Expires            Service principal
03/03/10 18:54:44  03/04/10 18:54:42  krbtgt/EXAMPLE.COM@EXAMPLE.COM
03/03/10 18:54:46  03/04/10 18:54:42  ldap/klas1.example.com@EXAMPLE.COM
~# _

Now the previously attempted authenticated query should work:

~# ldapsearch -LLL ou=people
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL data security layer installed.
dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

~# _

Also, under these circumstances the ldapwhoami command behaves more like whoami:

~# whoami
~# ldapwhoami
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL data security layer installed.
~# _

Authentication is now necessary for all LDAP commands, but thanks to Kerberos' single-sign-on technology this is hardly an inconvenience.

17. Admin passwd removal

Having verified that Kerberos authentication is now working for the admin user, it should be noted that this entry's original LDAP password is still available for use:

~# ldapsearch -xWLLL -D cn=admin,dc=example,dc=com ou=people
Enter LDAP Password: cerastes
dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

~# _

Remember that when using simple authentication the passwords are sent as plain text. When this happens over the network it represents a potential security hazard − especially in the case of the admin account. Therefore, this password should be disabled. To do this, create a new file, called ~/admin-pw.ldif, with the following contents:

dn: cn=admin,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {CRYPT}*

This modification will change the admin password to an invalid hash. Apply it with the ldapmodify command:

~# ldapmodify -f ~/admin-pw.ldif
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL data security layer installed.
modifying entry "cn=admin,dc=example,dc=com"

~# _

As a result, the former search command using simple authentication will no longer work:

~# ldapsearch -xWLLL -D cn=admin,dc=example,dc=com ou=people
Enter LDAP Password: cerastes
ldap_bind: Invalid credentials (49)
~# _

18. Debconf reconfig

From this point on, a more detailed level of questioning will be required from debconf. To achieve this, run the following command:

~# dpkg-reconfigure debconf

Answer the questions as follows:

Interface to use: Dialog
Ignore questions with a priority less than: low

19. AFS kernel module

The objective here is to build and install the OpenAFS kernel module from source. Start by installing the module assistant:

~# apt-get install module-assistant

This gets installed:

module-assistant              0.11.3                               tool to make module package creation easier

Then use it to download the source code for the AFS kernel module, compile and install it:

~# m-a prepare openafs ; m-a a-i openafs

As a result, 49 new packages will be installed in four stages, the last of which involves the compilation and installation of the AFS kernel module:

binutils                      2.18.1~cvs20080103-7                 The GNU assembler, linker and binary utilities
bison                         1:2.3.dfsg-5                         A parser generator that is compatible with YACC
build-essential               11.4                                 Informational list of build-essential packages
bzip2                         1.0.5-1                              high-quality block-sorting file compressor - utilit
cpp                           4:4.3.2-2                            The GNU C preprocessor (cpp)
cpp-4.1                       4.1.2-25                             The GNU C preprocessor
cpp-4.3                       4.3.2-1.1                            The GNU C preprocessor
debhelper                     7.0.15                               helper programs for debian/rules
dpkg-dev                      1.14.28                              Debian package development tools
flex                          2.5.35-6                             A fast lexical analyzer generator.
g++                           4:4.3.2-2                            The GNU C++ compiler
g++-4.3                       4.3.2-1.1                            The GNU C++ compiler
gcc                           4:4.3.2-2                            The GNU C compiler
gcc-4.1                       4.1.2-25                             The GNU C compiler
gcc-4.1-base                  4.1.2-25                             The GNU Compiler Collection (base package)
gcc-4.3                       4.3.2-1.1                            The GNU C compiler
gettext                       0.17-4                               GNU Internationalization utilities
html2text                     1.3.2a-5                             advanced HTML to text converter
intltool-debian               0.35.0+20060710.1                    Help i18n of RFC822 compliant config files
libc6-dev                     2.7-18lenny2                         GNU C Library: Development Libraries and Header Fil
libcompress-raw-zlib-perl     2.012-1lenny1                        low-level interface to zlib compression library
libcompress-zlib-perl         2.012-1                              Perl module for creation and manipulation of gzip f
libdigest-hmac-perl           1.01-7                               create standard message integrity checks
libdigest-sha1-perl           2.11-2+b1                            NIST SHA-1 message digest algorithm
libfile-remove-perl           1.42-1                               remove files and directories, accepts wildcards
libgmp3c2                     2:4.2.2+dfsg-3                       Multiprecision arithmetic library
libgomp1                      4.3.2-1.1                            GCC OpenMP (GOMP) support library
libio-compress-base-perl      2.012-1                              Base Class for IO::Compress modules
libio-compress-zlib-perl      2.012-1                              Perl interface to zlib
libio-stringy-perl            2.110-4                              Perl modules for IO from scalars and arrays
libmail-box-perl              2.082-2                              Manage a message-folder
libmail-sendmail-perl         0.79-5                               Send email from a perl script
libmailtools-perl             2.03-1                               Manipulate email in perl programs
libmime-types-perl            1.24-1                               Perl extension for determining MIME types and Trans
libmpfr1ldbl                  2.3.1.dfsg.1-2                       multiple precision floating-point computation
libobject-realize-later-perl  0.18-1                               Delayed creation of objects
libstdc++6-4.3-dev            4.3.2-1.1                            The GNU Standard C++ Library v3 (development files)
libsys-hostname-long-perl     1.4-2                                Figure out the long (fully-qualified) hostname
libtimedate-perl              1.1600-9                             Time and date functions for Perl
liburi-perl                   1.35.dfsg.1-1                        Manipulates and accesses URI strings
libuser-identity-perl         0.92-2                               manages different identities/roles used by a physic
linux-headers-2.6.26-2-686    2.6.26-21lenny3                      Header files for Linux 2.6.26-2-686
linux-headers-2.6.26-2-common 2.6.26-21lenny3                      Common header files for Linux 2.6.26-2
linux-kbuild-2.6.26           2.6.26-3                             Kbuild infrastructure for Linux 2.6.26
linux-libc-dev                2.6.26-21lenny3                      Linux support headers for userspace development
make                          3.81-5                               The GNU version of the "make" utility.
openafs-modules-2.6.26-2-686  1.4.7.dfsg1-6+lenny2+2.6.26-21lenny3 AFS distributed filesystem kernel module
openafs-modules-source        1.4.7.dfsg1-6+lenny2                 AFS distributed filesystem kernel module source
po-debconf                    1.0.15                               manage translated Debconf templates files with gett

After it has been built and installed, test the OpenAFS kernel module by loading it:

~# modprobe openafs

Here it what it looks like when the module has been loaded:

~# lsmod |grep afs
openafs               473948  0 

20. OpenAFS client install

Install the OpenAFS client. Now install these two packages:

~# apt-get install openafs-{client,krb5}

Only these two packages are installed as a result:

openafs-client                1.4.7.dfsg1-6+lenny2                 AFS distributed filesystem client support
openafs-krb5                  1.4.7.dfsg1-6+lenny2                 AFS distributed filesystem Kerberos 5 integration

Following the installation process, debconf will ask a few questions regarding the openafs-client package. Answer them as follows:

AFS cell this workstation belongs to: example.com
Size of AFS cache in kB: 50000
Run Openafs client now and at boot? No
Look up AFS cells in DNS? Yes
Encrypt authenticated traffic with AFS fileserver? No
Dynamically generate the contents of /afs? Yes
Use fakestat to avoid hangs when listing /afs? Yes
DB server host names for your home cell: klas1

Regarding the AFS cache, the default size is about 50 MB and is located in the /var/cache/openafs/ directory. Often, the cache is increased to around 512 MB, but usually less than 1 GB; larger cache sizes may lengthen the startup time, as all files within the cache must be prechecked with the servers. It is vital that OpenAFS is never in danger of running out of cache space, since it is not designed to handle such situations gracefully. A requirement is also that an ext2 or ext3 file system is used for the cache directory; a file containing such a file system, or a dedicated partition can be used for this purpose, but its even possible to use a memory-based cache, which offers signifigant performance benefits.

21. OpenAFS server install

To install the OpenAFS server, start by installing these two packages:

~# apt-get install openafs-{fileserver,dbserver}

These are also the only two packages that are installed as a result:

openafs-dbserver              1.4.7.dfsg1-6+lenny2                 AFS distributed filesystem database server
openafs-fileserver            1.4.7.dfsg1-6+lenny2                 AFS distributed filesystem file server

One question must be answered for the openafs-fileserver package:

Cell this server serves files for: example.com

22. AFS princ & keytab

Use kadmin.local to create a Kerberos principal for the AFS service and a matching keytab file by issuing a few commands:

~# kadmin -p admin
Authenticating as principal admin with password.
Password for admin@EXAMPLE.COM: cerastes
kadmin:  addprinc -randkey -e des-cbc-crc:normal afs/example.com
WARNING: no policy specified for afs/example.com@EXAMPLE.COM; 
defaulting to no policy
Principal "afs/example.com@EXAMPLE.COM" created.
kadmin:  ktadd -k /tmp/afs.keytab -e des-cbc-crc:normal afs/example.com
Entry for principal afs/example.com with kvno 3, encryption type 
DES cbc mode with CRC-32 added to keytab WRFILE:/tmp/afs.keytab.
kadmin:  q
~# _

This principal is not host-specific, since it is meant to be used not only by this AFS server, but also by any other AFS servers that may eventually be added to this cell.

The key created above is a single-DES key, which is relatively weak compared to what is offered by newer versions of Kerberos, but improvements are coming: newer versions of OpenAFS already include AES encryption, although this has not yet made it into the standard releases.

In the mean time, these weak cryptographic keys are accepted because the version of Kerberos V used here, 1.6, includes an apparently undocumented [libdefaults] setting in /etc/krb5.confallow_weak_crypto − that by default is set to "true." However, as of version 1.8 its default has been changed to "false." So, if Debian's next stable release does include Kerberos V 1.8, but not the new cryptographic improvements for OpenAFS, then allow_weak_crypto = true will have to be added to /etc/krb5.conf.

After the key has been created, it must be loaded into the AFS key file:

~# asetkey add 3 /tmp/afs.keytab afs/example.com
~# _

The number 3 reflects the key version number, which must match KVNO number reported after the ktadd command during the previous kadmin session.

To verify that the new key has been loaded and that there is only one Kerberos key in the AFS keyfile, run the following command:

~# bos listkeys klas1 -localauth
key 3 has cksum 2504619324
Keys last changed on Wed Mar  3 19:23:37 2010.
All done.
~# _

The results are approximately what should be expected.

23. AFS partition

OpenAFS is usually set up to work with dedicated partitions of which each server can maintain up to 256. These partitions are associated with mount points just below the root that follow a particular naming convention, /vicepXX/, where XX can be any letter, or two-letter combination. In this exercise, a separate partition, /dev/hdb1, will be formatted with the ext3 file system and mounted at /vicepa/.

Actually, in cases where a separate partition is not available, it is also possible for OpenAFS to simply use a /vicepXX/ directory in the root partition. This is because OpenAFS does not require any particular low-level format for its partitions. AFS partitions can therefore be explored with ordinary UNIX tools, although the data stored therein is structured in a way that is only meaningful to OpenAFS.

Assuming a partition has already been created on the disk, format it with:

~# mkfs.ext3 /dev/hdb1
mke2fs 1.41.3 (12-Oct-2008)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
262144 inodes, 1048564 blocks
52428 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1073741824
32 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736

Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
~# _

Then edit /etc/fstab and add this line to the end of the file:

/dev/hdb1       /vicepa         ext3    defaults        0       0

Now create the mount point and mount the new partition:

~# mkdir /vicepa ; mount /vicepa/
~# _

24. Cell creation

With OpenAFS, information regarding file locations, server systems and namespace management is centrally controlled and stored in custom-built internal databases that are replicated to reduce the risk of server failure. Should such a failure occur, the clients can automatically fail-over to the next available database server. Together, these database and file servers and their clients are referred to as an AFS cell. Run the script that will create a new cell:

~# afs-newcell

In order to set up a new AFS cell, you must meet the following:

1) You need a working Kerberos realm with Kerberos4 support.  You
   should install Heimdal with KTH Kerberos compatibility or MIT
   Kerberos 5.

2) You need to create the single-DES AFS key and load it into
   /etc/openafs/server/KeyFile.  If your cell's name is the same as
   your Kerberos realm then create a principal called afs.  Otherwise,
   create a principal called afs/cellname in your realm.  The cell
   name should be all lower case, unlike Kerberos realms which are all
   upper case.  You can use asetkey from the openafs-krb5 package, or
   if you used AFS3 salt to create the key, the bos addkey command.

3) This machine should have a filesystem mounted on /vicepa.  If you
   do not have a free partition, then create a large file by using dd
   to extract bytes from /dev/zero.  Create a filesystem on this file
   and mount it using -oloop.

4) You will need an administrative principal created in a Kerberos
   realm.  This principal will be added to susers and
   system:administrators and thus will be able to run administrative
   commands.  Generally the user is a root or admin instance of some
   administrative user.  For example if jruser is an administrator then
   it would be reasonable to create jruser/admin (or jruser/root) and
   specify that as the user to be added in this script.

5) The AFS client must not be running on this workstation.  It will be
   at the end of this script.

Do you meet these requirements? [y/n] y
If the fileserver is not running, this may hang for 30 seconds.
/etc/init.d/openafs-fileserver stop
What administrative principal should be used? admin

/etc/openafs/server/CellServDB already exists, renaming to .old
/etc/init.d/openafs-fileserver start
bos adduser klas1.example.com admin -localauth

Creating initial protection database.  This will print some errors
about an id already existing and a bad ubik magic.  These errors can
be safely ignored.

pt_util: /var/lib/openafs/db/prdb.DB0: Bad UBIK_MAGIC. Is 0 should be 
Ubik Version is: 2.0
Error while creating system:administrators: Entry for id already exists

bos create klas1.example.com ptserver simple /usr/lib/openafs/ptserver 
bos create klas1.example.com vlserver simple /usr/lib/openafs/vlserver 
bos create klas1.example.com fs fs -cmd '/usr/lib/openafs/fileserver -p 23 
-busyat 600 -rxpck 400 -s 1200 -l 1200 -cb 65535 -b 240 -vc 1200' -cmd 
/usr/lib/openafs/volserver -cmd /usr/lib/openafs/salvager -localauth
bos setrestart klas1.example.com -time never -general -localauth
Waiting for database elections: done.
vos create klas1.example.com a root.afs -localauth
Volume 536870912 created on partition /vicepa of klas1.example.com
/etc/init.d/openafs-client force-start
Starting AFS services: openafs afsd.
afsd: All AFS daemons started.

Now, get tokens as admin in the example.com cell.
Then, run afs-rootvol.
~# _

25. AFS tokens

Obtain AFS tokens as the admin user, as advised near the end of the afs-newcell session:

~# kinit admin
Password for admin@EXAMPLE.COM: cerastes
~# aklog
~# klist -5f
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE.COM

Valid starting     Expires            Service principal
03/03/10 19:28:54  03/04/10 19:28:51  krbtgt/EXAMPLE.COM@EXAMPLE.COM
	Flags: FPIA
03/03/10 19:29:02  03/04/10 19:28:51  afs/example.com@EXAMPLE.COM
	Flags: FPAT
~# tokens

Tokens held by the Cache Manager:

User's (AFS ID 1) tokens for afs@example.com [Expires Mar  4 19:28]
   --End of list--
~# _

26. Root volume creation

OpenAFS stores files in structures called volumes and the first volume of an AFS cell is always called root.afs. Create it now with this command:

~# afs-rootvol

In order to set up the root.afs volume, you must meet the following

1) The cell must be configured, running a database server with a
   volume location and protection server.  The afs-newcell script will
   set up these services.

2) You must be logged into the cell with tokens in for a user in
   system:administrators and with a principal that is in the UserList
   file of the servers in the cell.

3) You need a fileserver in the cell with partitions mounted and a
   root.afs volume created.  Presumably, it has no volumes on it,
   although the script will work so long as nothing besides root.afs
   exists.  The afs-newcell script will set up the file server.

4) The AFS client must be running pointed at the new cell.
Do you meet these conditions? (y/n) y

You will need to select a server (hostname) and AFS partition on which to
create the root volumes.

What AFS Server should volumes be placed on? klas1
What partition? [a] a

vos create klas1 a root.cell -localauth
Volume 536870915 created on partition /vicepa of klas1
fs mkm /afs/example.com/.root.afs root.afs -rw
fs sa /afs/example.com/.root.afs system:anyuser rl
fs mkm /afs/example.com/.root.afs/example.com root.cell -cell example.com -fast || true
fs mkm /afs/example.com/.root.afs/grand.central.org root.cell -cell grand.central.org -fast || true
fs mkm /afs/example.com/.root.afs/wu-wien.ac.at root.cell -cell wu-wien.ac.at -fast || true
fs mkm /afs/example.com/.root.afs/hephy.at root.cell -cell hephy.at -fast || true
fs mkm /afs/example.com/.root.afs/cgv.tugraz.at root.cell -cell cgv.tugraz.at -fast || true
fs mkm /afs/example.com/.root.afs/itp.tugraz.at root.cell -cell itp.tugraz.at -fast || true
fs mkm /afs/example.com/.root.afs/sums.math.mcgill.ca root.cell -cell sums.math.mcgill.ca -fast || true
fs mkm /afs/example.com/.root.afs/cern.ch root.cell -cell cern.ch -fast || true
fs mkm /afs/example.com/.root.afs/ams.cern.ch root.cell -cell ams.cern.ch -fast || true
fs mkm /afs/example.com/.root.afs/epfl.ch root.cell -cell epfl.ch -fast || true
fs mkm /afs/example.com/.root.afs/ethz.ch root.cell -cell ethz.ch -fast || true
fs mkm /afs/example.com/.root.afs/psi.ch root.cell -cell psi.ch -fast || true
fs mkm /afs/example.com/.root.afs/extundo.com root.cell -cell extundo.com -fast || true
fs mkm /afs/example.com/.root.afs/membrain.com root.cell -cell membrain.com -fast || true
fs mkm /afs/example.com/.root.afs/setfilepointer.com root.cell -cell setfilepointer.com -fast || true
fs mkm /afs/example.com/.root.afs/sodre.cx root.cell -cell sodre.cx -fast || true
fs mkm /afs/example.com/.root.afs/ruk.cuni.cz root.cell -cell ruk.cuni.cz -fast || true
fs mkm /afs/example.com/.root.afs/desy.de root.cell -cell desy.de -fast || true
fs mkm /afs/example.com/.root.afs/gppc.de root.cell -cell gppc.de -fast || true
fs mkm /afs/example.com/.root.afs/cms.hu-berlin.de root.cell -cell cms.hu-berlin.de -fast || true
fs mkm /afs/example.com/.root.afs/ifh.de root.cell -cell ifh.de -fast || true
fs mkm /afs/example.com/.root.afs/lrz-muenchen.de root.cell -cell lrz-muenchen.de -fast || true
fs mkm /afs/example.com/.root.afs/ipp-garching.mpg.de root.cell -cell ipp-garching.mpg.de -fast || true
fs mkm /afs/example.com/.root.afs/mpe.mpg.de root.cell -cell mpe.mpg.de -fast || true
fs mkm /afs/example.com/.root.afs/i1.informatik.rwth-aachen.de root.cell -cell i1.informatik.rwth-aachen.de -fast || true
fs mkm /afs/example.com/.root.afs/combi.tfh-wildau.de root.cell -cell combi.tfh-wildau.de -fast || true
fs mkm /afs/example.com/.root.afs/tu-bs.de root.cell -cell tu-bs.de -fast || true
fs mkm /afs/example.com/.root.afs/tu-chemnitz.de root.cell -cell tu-chemnitz.de -fast || true
fs mkm /afs/example.com/.root.afs/e18.ph.tum.de root.cell -cell e18.ph.tum.de -fast || true
fs mkm /afs/example.com/.root.afs/uni-bonn.de root.cell -cell uni-bonn.de -fast || true
fs mkm /afs/example.com/.root.afs/atlass01.physik.uni-bonn.de root.cell -cell atlass01.physik.uni-bonn.de -fast || true
fs mkm /afs/example.com/.root.afs/uni-freiburg.de root.cell -cell uni-freiburg.de -fast || true
fs mkm /afs/example.com/.root.afs/physik.uni-freiburg.de root.cell -cell physik.uni-freiburg.de -fast || true
fs mkm /afs/example.com/.root.afs/urz.uni-heidelberg.de root.cell -cell urz.uni-heidelberg.de -fast || true
fs mkm /afs/example.com/.root.afs/uni-hohenheim.de root.cell -cell uni-hohenheim.de -fast || true
fs mkm /afs/example.com/.root.afs/rz.uni-jena.de root.cell -cell rz.uni-jena.de -fast || true
fs mkm /afs/example.com/.root.afs/impetus.uni-koeln.de root.cell -cell impetus.uni-koeln.de -fast || true
fs mkm /afs/example.com/.root.afs/meteo.uni-koeln.de root.cell -cell meteo.uni-koeln.de -fast || true
fs mkm /afs/example.com/.root.afs/rrz.uni-koeln.de root.cell -cell rrz.uni-koeln.de -fast || true
fs mkm /afs/example.com/.root.afs/physik.uni-mainz.de root.cell -cell physik.uni-mainz.de -fast || true
fs mkm /afs/example.com/.root.afs/uni-mannheim.de root.cell -cell uni-mannheim.de -fast || true
fs mkm /afs/example.com/.root.afs/uni-paderborn.de root.cell -cell uni-paderborn.de -fast || true
fs mkm /afs/example.com/.root.afs/physik.uni-wuppertal.de root.cell -cell physik.uni-wuppertal.de -fast || true
fs mkm /afs/example.com/.root.afs/s-et.aau.dk root.cell -cell s-et.aau.dk -fast || true
fs mkm /afs/example.com/.root.afs/ies.auc.dk root.cell -cell ies.auc.dk -fast || true
fs mkm /afs/example.com/.root.afs/asu.edu root.cell -cell asu.edu -fast || true
fs mkm /afs/example.com/.root.afs/eecs.berkeley.edu root.cell -cell eecs.berkeley.edu -fast || true
fs mkm /afs/example.com/.root.afs/hep.caltech.edu root.cell -cell hep.caltech.edu -fast || true
fs mkm /afs/example.com/.root.afs/ugcs.caltech.edu root.cell -cell ugcs.caltech.edu -fast || true
fs mkm /afs/example.com/.root.afs/clarkson.edu root.cell -cell clarkson.edu -fast || true
fs mkm /afs/example.com/.root.afs/andrew.cmu.edu root.cell -cell andrew.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/club.cc.cmu.edu root.cell -cell club.cc.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/chem.cmu.edu root.cell -cell chem.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.cmu.edu root.cell -cell cs.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/ece.cmu.edu root.cell -cell ece.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/scotch.ece.cmu.edu root.cell -cell scotch.ece.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/qatar.cmu.edu root.cell -cell qatar.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/sbp.ri.cmu.edu root.cell -cell sbp.ri.cmu.edu -fast || true
fs mkm /afs/example.com/.root.afs/cnf.cornell.edu root.cell -cell cnf.cornell.edu -fast || true
fs mkm /afs/example.com/.root.afs/msc.cornell.edu root.cell -cell msc.cornell.edu -fast || true
fs mkm /afs/example.com/.root.afs/dbic.dartmouth.edu root.cell -cell dbic.dartmouth.edu -fast || true
fs mkm /afs/example.com/.root.afs/northstar.dartmouth.edu root.cell -cell northstar.dartmouth.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.hm.edu root.cell -cell cs.hm.edu -fast || true
fs mkm /afs/example.com/.root.afs/eecs.harvard.edu root.cell -cell eecs.harvard.edu -fast || true
fs mkm /afs/example.com/.root.afs/iastate.edu root.cell -cell iastate.edu -fast || true
fs mkm /afs/example.com/.root.afs/athena.mit.edu root.cell -cell athena.mit.edu -fast || true
fs mkm /afs/example.com/.root.afs/dev.mit.edu root.cell -cell dev.mit.edu -fast || true
fs mkm /afs/example.com/.root.afs/net.mit.edu root.cell -cell net.mit.edu -fast || true
fs mkm /afs/example.com/.root.afs/sipb.mit.edu root.cell -cell sipb.mit.edu -fast || true
fs mkm /afs/example.com/.root.afs/soap.mit.edu root.cell -cell soap.mit.edu -fast || true
fs mkm /afs/example.com/.root.afs/msu.edu root.cell -cell msu.edu -fast || true
fs mkm /afs/example.com/.root.afs/nd.edu root.cell -cell nd.edu -fast || true
fs mkm /afs/example.com/.root.afs/crc.nd.edu root.cell -cell crc.nd.edu -fast || true
fs mkm /afs/example.com/.root.afs/pitt.edu root.cell -cell pitt.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.pitt.edu root.cell -cell cs.pitt.edu -fast || true
fs mkm /afs/example.com/.root.afs/psc.edu root.cell -cell psc.edu -fast || true
fs mkm /afs/example.com/.root.afs/scoobydoo.psc.edu root.cell -cell scoobydoo.psc.edu -fast || true
fs mkm /afs/example.com/.root.afs/cede.psu.edu root.cell -cell cede.psu.edu -fast || true
fs mkm /afs/example.com/.root.afs/rose-hulman.edu root.cell -cell rose-hulman.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.rose-hulman.edu root.cell -cell cs.rose-hulman.edu -fast || true
fs mkm /afs/example.com/.root.afs/rpi.edu root.cell -cell rpi.edu -fast || true
fs mkm /afs/example.com/.root.afs/hep.sc.edu root.cell -cell hep.sc.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.stanford.edu root.cell -cell cs.stanford.edu -fast || true
fs mkm /afs/example.com/.root.afs/ir.stanford.edu root.cell -cell ir.stanford.edu -fast || true
fs mkm /afs/example.com/.root.afs/slac.stanford.edu root.cell -cell slac.stanford.edu -fast || true
fs mkm /afs/example.com/.root.afs/ucdavis.edu root.cell -cell ucdavis.edu -fast || true
fs mkm /afs/example.com/.root.afs/home.ucdavis.edu root.cell -cell home.ucdavis.edu -fast || true
fs mkm /afs/example.com/.root.afs/physics.ucsb.edu root.cell -cell physics.ucsb.edu -fast || true
fs mkm /afs/example.com/.root.afs/cats.ucsc.edu root.cell -cell cats.ucsc.edu -fast || true
fs mkm /afs/example.com/.root.afs/acm.uiuc.edu root.cell -cell acm.uiuc.edu -fast || true
fs mkm /afs/example.com/.root.afs/illigal.uiuc.edu root.cell -cell illigal.uiuc.edu -fast || true
fs mkm /afs/example.com/.root.afs/ncsa.uiuc.edu root.cell -cell ncsa.uiuc.edu -fast || true
fs mkm /afs/example.com/.root.afs/umbc.edu root.cell -cell umbc.edu -fast || true
fs mkm /afs/example.com/.root.afs/glue.umd.edu root.cell -cell glue.umd.edu -fast || true
fs mkm /afs/example.com/.root.afs/wam.umd.edu root.cell -cell wam.umd.edu -fast || true
fs mkm /afs/example.com/.root.afs/umich.edu root.cell -cell umich.edu -fast || true
fs mkm /afs/example.com/.root.afs/atlas.umich.edu root.cell -cell atlas.umich.edu -fast || true
fs mkm /afs/example.com/.root.afs/citi.umich.edu root.cell -cell citi.umich.edu -fast || true
fs mkm /afs/example.com/.root.afs/lsa.umich.edu root.cell -cell lsa.umich.edu -fast || true
fs mkm /afs/example.com/.root.afs/sph.umich.edu root.cell -cell sph.umich.edu -fast || true
fs mkm /afs/example.com/.root.afs/isis.unc.edu root.cell -cell isis.unc.edu -fast || true
fs mkm /afs/example.com/.root.afs/physics.unc.edu root.cell -cell physics.unc.edu -fast || true
fs mkm /afs/example.com/.root.afs/uncc.edu root.cell -cell uncc.edu -fast || true
fs mkm /afs/example.com/.root.afs/eng.utah.edu root.cell -cell eng.utah.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.uwm.edu root.cell -cell cs.uwm.edu -fast || true
fs mkm /afs/example.com/.root.afs/cs.wisc.edu root.cell -cell cs.wisc.edu -fast || true
fs mkm /afs/example.com/.root.afs/engr.wisc.edu root.cell -cell engr.wisc.edu -fast || true
fs mkm /afs/example.com/.root.afs/hep.wisc.edu root.cell -cell hep.wisc.edu -fast || true
fs mkm /afs/example.com/.root.afs/physics.wisc.edu root.cell -cell physics.wisc.edu -fast || true
fs mkm /afs/example.com/.root.afs/ciemat.es root.cell -cell ciemat.es -fast || true
fs mkm /afs/example.com/.root.afs/ifca.unican.es root.cell -cell ifca.unican.es -fast || true
fs mkm /afs/example.com/.root.afs/ific.uv.es root.cell -cell ific.uv.es -fast || true
fs mkm /afs/example.com/.root.afs/biocenter.helsinki.fi root.cell -cell biocenter.helsinki.fi -fast || true
fs mkm /afs/example.com/.root.afs/dapnia.saclay.cea.fr root.cell -cell dapnia.saclay.cea.fr -fast || true
fs mkm /afs/example.com/.root.afs/grif.fr root.cell -cell grif.fr -fast || true
fs mkm /afs/example.com/.root.afs/in2p3.fr root.cell -cell in2p3.fr -fast || true
fs mkm /afs/example.com/.root.afs/mcc.ac.gb root.cell -cell mcc.ac.gb -fast || true
fs mkm /afs/example.com/.root.afs/anl.gov root.cell -cell anl.gov -fast || true
fs mkm /afs/example.com/.root.afs/rhic.bnl.gov root.cell -cell rhic.bnl.gov -fast || true
fs mkm /afs/example.com/.root.afs/usatlas.bnl.gov root.cell -cell usatlas.bnl.gov -fast || true
fs mkm /afs/example.com/.root.afs/fnal.gov root.cell -cell fnal.gov -fast || true
fs mkm /afs/example.com/.root.afs/ic-afs.arc.nasa.gov root.cell -cell ic-afs.arc.nasa.gov -fast || true
fs mkm /afs/example.com/.root.afs/jpl.nasa.gov root.cell -cell jpl.nasa.gov -fast || true
fs mkm /afs/example.com/.root.afs/nersc.gov root.cell -cell nersc.gov -fast || true
fs mkm /afs/example.com/.root.afs/bme.hu root.cell -cell bme.hu -fast || true
fs mkm /afs/example.com/.root.afs/kfki.hu root.cell -cell kfki.hu -fast || true
fs mkm /afs/example.com/.root.afs/caspur.it root.cell -cell caspur.it -fast || true
fs mkm /afs/example.com/.root.afs/enea.it root.cell -cell enea.it -fast || true
fs mkm /afs/example.com/.root.afs/fusione.it root.cell -cell fusione.it -fast || true
fs mkm /afs/example.com/.root.afs/icemb.it root.cell -cell icemb.it -fast || true
fs mkm /afs/example.com/.root.afs/infn.it root.cell -cell infn.it -fast || true
fs mkm /afs/example.com/.root.afs/ba.infn.it root.cell -cell ba.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/kloe.infn.it root.cell -cell kloe.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/le.infn.it root.cell -cell le.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/lnf.infn.it root.cell -cell lnf.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/lngs.infn.it root.cell -cell lngs.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/pi.infn.it root.cell -cell pi.infn.it -fast || true
fs mkm /afs/example.com/.root.afs/psm.it root.cell -cell psm.it -fast || true
fs mkm /afs/example.com/.root.afs/tgrid.it root.cell -cell tgrid.it -fast || true
fs mkm /afs/example.com/.root.afs/ictp.trieste.it root.cell -cell ictp.trieste.it -fast || true
fs mkm /afs/example.com/.root.afs/math.unifi.it root.cell -cell math.unifi.it -fast || true
fs mkm /afs/example.com/.root.afs/ing.uniroma1.it root.cell -cell ing.uniroma1.it -fast || true
fs mkm /afs/example.com/.root.afs/dia.uniroma3.it root.cell -cell dia.uniroma3.it -fast || true
fs mkm /afs/example.com/.root.afs/vn.uniroma3.it root.cell -cell vn.uniroma3.it -fast || true
fs mkm /afs/example.com/.root.afs/italia root.cell -cell italia -fast || true
fs mkm /afs/example.com/.root.afs/cmf.nrl.navy.mil root.cell -cell cmf.nrl.navy.mil -fast || true
fs mkm /afs/example.com/.root.afs/lcp.nrl.navy.mil root.cell -cell lcp.nrl.navy.mil -fast || true
fs mkm /afs/example.com/.root.afs/es.net root.cell -cell es.net -fast || true
fs mkm /afs/example.com/.root.afs/laroia.net root.cell -cell laroia.net -fast || true
fs mkm /afs/example.com/.root.afs/sinenomine.net root.cell -cell sinenomine.net -fast || true
fs mkm /afs/example.com/.root.afs/slackers.net root.cell -cell slackers.net -fast || true
fs mkm /afs/example.com/.root.afs/tproa.net root.cell -cell tproa.net -fast || true
fs mkm /afs/example.com/.root.afs/interdose.net root.cell -cell interdose.net -fast || true
fs mkm /afs/example.com/.root.afs/nikhef.nl root.cell -cell nikhef.nl -fast || true
fs mkm /afs/example.com/.root.afs/1ts.org root.cell -cell 1ts.org -fast || true
fs mkm /afs/example.com/.root.afs/acm-csuf.org root.cell -cell acm-csuf.org -fast || true
fs mkm /afs/example.com/.root.afs/bazquux.org root.cell -cell bazquux.org -fast || true
fs mkm /afs/example.com/.root.afs/coed.org root.cell -cell coed.org -fast || true
fs mkm /afs/example.com/.root.afs/dementia.org root.cell -cell dementia.org -fast || true
fs mkm /afs/example.com/.root.afs/dsrw.org root.cell -cell dsrw.org -fast || true
fs mkm /afs/example.com/.root.afs/hackish.org root.cell -cell hackish.org -fast || true
fs mkm /afs/example.com/.root.afs/idahofuturetruck.org root.cell -cell idahofuturetruck.org -fast || true
fs mkm /afs/example.com/.root.afs/mrph.org root.cell -cell mrph.org -fast || true
fs mkm /afs/example.com/.root.afs/nimlabs.org root.cell -cell nimlabs.org -fast || true
fs mkm /afs/example.com/.root.afs/nomh.org root.cell -cell nomh.org -fast || true
fs mkm /afs/example.com/.root.afs/oc7.org root.cell -cell oc7.org -fast || true
fs mkm /afs/example.com/.root.afs/riscpkg.org root.cell -cell riscpkg.org -fast || true
fs mkm /afs/example.com/.root.afs/kth.se root.cell -cell kth.se -fast || true
fs mkm /afs/example.com/.root.afs/hallf.kth.se root.cell -cell hallf.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/isk.kth.se root.cell -cell isk.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/it.kth.se root.cell -cell it.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/md.kth.se root.cell -cell md.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/mech.kth.se root.cell -cell mech.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/nada.kth.se root.cell -cell nada.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/pdc.kth.se root.cell -cell pdc.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/stacken.kth.se root.cell -cell stacken.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/syd.kth.se root.cell -cell syd.kth.se -fast || true
fs mkm /afs/example.com/.root.afs/physto.se root.cell -cell physto.se -fast || true
fs mkm /afs/example.com/.root.afs/sanchin.se root.cell -cell sanchin.se -fast || true
fs mkm /afs/example.com/.root.afs/su.se root.cell -cell su.se -fast || true
fs mkm /afs/example.com/.root.afs/f9.ijs.si root.cell -cell f9.ijs.si -fast || true
fs mkm /afs/example.com/.root.afs/p-ng.si root.cell -cell p-ng.si -fast || true
fs mkm /afs/example.com/.root.afs/hep-ex.physics.metu.edu.tr root.cell -cell hep-ex.physics.metu.edu.tr -fast || true
fs mkm /afs/example.com/.root.afs/phy.bris.ac.uk root.cell -cell phy.bris.ac.uk -fast || true
fs mkm /afs/example.com/.root.afs/inf.ed.ac.uk root.cell -cell inf.ed.ac.uk -fast || true
fs mkm /afs/example.com/.root.afs/ic.ac.uk root.cell -cell ic.ac.uk -fast || true
fs mkm /afs/example.com/.root.afs/hep.man.ac.uk root.cell -cell hep.man.ac.uk -fast || true
fs mkm /afs/example.com/.root.afs/rl.ac.uk root.cell -cell rl.ac.uk -fast || true
fs sa /afs/example.com system:anyuser rl
fs mkm /afs/example.com/.root.afs/.example.com root.cell -cell example.com -rw
fs mkm /afs/example.com/.root.afs/.root.afs root.afs -rw
vos create klas1 a user -localauth
Volume 536870918 created on partition /vicepa of klas1
fs mkm /afs/example.com/user user 
fs sa /afs/example.com/user system:anyuser rl
vos create klas1 a service -localauth
Volume 536870921 created on partition /vicepa of klas1
fs mkm /afs/example.com/service service 
fs sa /afs/example.com/service system:anyuser rl
ln -s example.com /afs/example.com/.root.afs/example
ln -s .example.com /afs/example.com/.root.afs/.example
fs rmm /afs/example.com/.root.afs
vos addsite klas1 a root.afs -localauth
Added replication site klas1 /vicepa for volume root.afs
vos addsite klas1 a root.cell -localauth
Added replication site klas1 /vicepa for volume root.cell
vos release root.afs -localauth
Released volume root.afs successfully
vos release root.cell -localauth
Released volume root.cell successfully
~# _

The answer given to the question "What partition?" − a − is the only one possible, because it relates to the previously configured AFS partition, /vicepa/.

27. AFS client & test

Now that the OpenAFS server is up and running, enable the OpenAFS client. It was installed much earlier, but configured not to start up automatically. Change that by editing /etc/openafs/afs.conf.client and changing the following line:


Now restart the client:

~# /etc/init.d/openafs-client restart
Stopping AFS services: afsd openafs.
Starting AFS services: openafs afsd.
afsd: All AFS daemons started.
~# _

After the AFS client has been started, check out the contents of the new AFS volume in the /afs/ directory:

~# ls /afs | head
~# ls /afs | wc -l
~# _

Besides those for the local cell, /afs/example.com and /afs/.example.com, the afs-rootvol script is also responsible for creating all of the other directories (AFS mount points) in the /afs/ directory, but these can easily be created or removed.

As opposed to the other 186 directories, those for the local cell are not visible globally; for that, a request would have to be submitted to have them included in the global CellServDB file. However, the fact that its existence has not been published officially does not necessarily mean that it is inaccessible from the Internet, so local security is still important.

28. New account & test

To add a new user account to this system, the account must be added to all three subsystems: Kerberos, OpenLDAP and OpenAFS. In this exercise, the new account will be ccolumbus and the password NewWorld. Start by creating the Kerberos account:

~# kadmin -p admin
Authenticating as principal admin with password.
Password for admin@EXAMPLE.COM: cerastes
kadmin:  addprinc ccolumbus
WARNING: no policy specified for ccolumbus@EXAMPLE.COM; 
defaulting to no policy
Enter password for principal "ccolumbus@EXAMPLE.COM": NewWorld
Re-enter password for principal "ccolumbus@EXAMPLE.COM": NewWorld
Principal "ccolumbus@EXAMPLE.COM" created.
kadmin:  q
~# _

Now create a matching LDAP user account for ccolumbus. First, create a file, called ~/ccolumbus.ldif, with the following contents:

dn: cn=ccolumbus,ou=groups,dc=example,dc=com
cn: ccolumbus
gidNumber: 20001
objectClass: top
objectClass: posixGroup

dn: uid=ccolumbus,ou=people,dc=example,dc=com
uid: ccolumbus
uidNumber: 20001
gidNumber: 20001
cn: Christopher
sn: Columbus
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
homeDirectory: /afs/example.com/user/c/cc/ccolumbus
userPassword: {CRYPT}*

Then apply this change with the ldapmodify command:

~# ldapadd -f ~/ccolumbus.ldif
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL data security layer installed.
adding new entry "cn=ccolumbus,ou=groups,dc=example,dc=com"

adding new entry "uid=ccolumbus,ou=people,dc=example,dc=com"

~# _

Before the AFS account can be created, obtain a Kerberos ticket for the admin account, as well as the matching AFS token for it:

~# kinit admin ; aklog
Password for admin@EXAMPLE.COM: cerastes
root@klas1:~# klist -5
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE.COM

Valid starting     Expires            Service principal
03/03/10 19:46:40  03/04/10 19:46:36  krbtgt/EXAMPLE.COM@EXAMPLE.COM
03/03/10 19:46:40  03/04/10 19:46:36  afs/example.com@EXAMPLE.COM
03/03/10 19:46:44  03/04/10 19:46:36  ldap/klas1.example.com@EXAMPLE.COM
~# _

Use the following command to create the new AFS account:

~# pts createuser -name ccolumbus -id 20001
User ccolumbus has id 20001
~# _

Now that the account for user ccolumbus exists in both Kerberos and OpenAFS, a corresponding AFS data volume must also be created for it that will be mounted in the location of the user's home directory in AFS:

~# vos create -server klas1 -partition /vicepa \
   -name user.ccolumbus -maxquota 100000
Volume 536870927 created on partition /vicepa of klas1
~# _

NB: Since the maximum space quota for the user is given in kilobytes, this will create a read/write volume of a mere 100 MB for the user. Should it later become necessary to increase the space quota for this volume, that can easily be done with the fs setquota command.

The following command will display information about the new volume:

~# vos examine -id user.ccolumbus
user.ccolumbus                    536870927 RW          2 K  On-line
    klas1.example.com /vicepa 
    RWrite  536870927 ROnly          0 Backup          0 
    MaxQuota     100000 K 
    Creation    Fri Feb 26 17:24:33 2010
    Copy        Fri Feb 26 17:24:33 2010
    Backup      Never
    Last Update Never

    RWrite: 536870927 
    number of sites -> 1
       server klas1.example.com partition /vicepa RW Site 
~# _

Once a volume has been created for an account, it should be mounted in a proper location: in this case /afs/example.com/user/c/cc/ccolumbus/. Instead of using a more shallow directory structure, such as e.g. /afs/example.com/user/ccolumbus/, the two extra sublevels follow an AFS convention that allows many libnss-afs and third-party management scripts to be used without modification.

Create the necessary two-sublevel directory structure to accomodate the new user volume:

~# mkdir -p /afs/example.com/user/c/cc
~# _

Now create the mount point for the new user volume:

~# fs mkmount -dir /afs/example.com/user/c/cc/ccolumbus \
   -vol user.ccolumbus -rw
~# _

If a mistake is made, the mount point can be removed again with the fs rmmount command.

This command can be used to view information about a (possible) AFS mount point:

~# fs lsmount -dir /afs/example.com/user/c/cc
'/afs/example.com/user/c/cc' is not a mount point.
~# fs lsmount -dir /afs/example.com/user/c/cc/ccolumbus
'/afs/example.com/user/c/cc/ccolumbus' is a mount point for 
volume '%user.ccolumbus'
~# _

Once this information is known, the vos examine command can be used to display information about the volume in question as shown above. Or, a related command can be used:

~# fs examine -p /afs/example.com/user/c/cc/ccolumbus
File /afs/example.com/user/c/cc/ccolumbus (536870927.1.1) contained 
in volume 536870927
Volume status for vid = 536870927 named user.ccolumbus
Current disk quota is 100000
Current blocks used are 2
The partition has 3843644 blocks available out of 3918688
~# _

Finally, there is the issue of permissions. By default, the new account does not have any rights in the volume that was just created for it:

~# fs listacl -path /afs/example.com/user/c/cc/ccolumbus
Access list for /afs/example.com/user/c/cc/ccolumbus is
Normal rights:
  system:administrators rlidwka
~# _

Grant the new account all rights to its namesake volume with this command:

~# fs setacl -dir /afs/example.com/user/c/cc/ccolumbus -acl ccolumbus all
~# _

Now verify that the new account has the appropriate access:

~# fs listacl -path /afs/example.com/user/c/cc/ccolumbus
Access list for /afs/example.com/user/c/cc/ccolumbus is
Normal rights:
  system:administrators rlidwka
  ccolumbus rlidwka
~# _

To test that the new account works, first logout of AFS and Kerberos and login as the new user:

~# unlog ; kdestroy
~# kinit ccolumbus ; aklog
Password for ccolumbus@EXAMPLE.COM: NewWorld
~# _

Now, as ccolumbus, make an attempt to write information to the account's new home directory:

~# date > /afs/example.com/user/c/cc/ccolumbus/date.txt
~# cat /afs/example.com/user/c/cc/ccolumbus/date.txt
Wed Mar  3 19:52:42 CET 2010

That was a success!

29. See also
30. Further reading
  • Eastlake D, Panitz A. 1999. RFC2606 − Reserved Top Level DNS Names. The Internet Society. HTML at the Internet FAQ Archives.
  • Hodges J, Morgan R. 2002. RFC3377 − Lightweight Directory Access Protocol (v3): Technical Specification. The Internet Society. HTML at the Internet FAQ Archives.
  • Kohl J, Neuman C. 1993. RFC1510 − The Kerberos Network Authentication Service (V5). HTML at the Internet FAQ Archives.
  • Linn J. 2000. RFC2743 − Generic Security Service Application Program Interface Version 2, Update 1. The Internet Society. HTML at the Internet FAQ Archives.
  • Myers J. 1997. RFC2222 − Simple Authentication and Security Layer (SASL). The Internet Society. HTML at the Internet FAQ Archives.
  • Wahl M, Howes T, Kille S. 1997. RFC2251 − Lightweight Directory Access Protocol (v3). The Internet Society. HTML at the Internet FAQ Archives.
  • Wilkinson S. 2008. OpenAFS, FOSDEM 2008. Video (15:30 minutes) at YouTube.
  • Wray J. 2000. RFC2744 − Generic Security Service API Version 2 : C-bindings. The Internet Society. HTML at the Internet FAQ Archives.
  • Yeong W, Howes T, Kille S. 1993. RFC1487 − X.500 Lightweight Directory Access Protocol. The Internet Society. HTML at the Internet FAQ Archives.

31. Sources
  • Campbell R. 1998. Managing AFS: The Andrew File System. Prentice Hall. ISBN 0-13-802729-3. 479 pp.
  • Carter G. 2003. LDAP System Administration. O'Reilly & Associates, Inc. ISBN 1-56592-491-6. 294 pp.
  • Garman J. 2003. Kerberos, The Definitive Guide. O'Reilly & Associates, Inc. ISBN-13 978-0-596-00403-3. 253 pp.
  • Massachusetts Institute of Technology. 1985-2007. Kerberos V5 System Administrator's Guide. HTML at the Massachusetts Institute of Technology (MIT). See section 6: Configuring Kerberos with OpenLDAP back-end.
  • Milicchio F, Gehrke WA. 2007. Distributed Services with OpenAFS. Springer-Verlag. ISBN-13 978-3-540-36633-1. 395 pp.
  • Ocelic D. 2006-2010. Debian GNU: Setting up MIT Kerberos 5. HTML at Spinlock Solutions.
  • Ocelic D. 2006-2010. Debian GNU: Setting up OpenAFS 1.4.x. HTML at Spinlock Solutions.
  • Ocelic D. 2006-2010. Debian GNU: Setting up OpenLDAP. HTML at Spinlock Solutions.
  • OpenAFS. 2000-2009. Documentation. HTML at OpenAFS.
  • Ubuntu documentation. Ubuntu 9.04. Ubuntu Server Guide, Network Authentication, Kerberos and LDAP. HTML at the Ubuntu 9.04 Server Guide.

Last modified: 2017-08-02, 17:50

©2003-2017 RJ Systems. Permission is granted to copy, distribute and/or modify the
content of this page under the terms of the OpenContent License, version 1.0.