Connecting to freeIPA with PHP

About

According to Wikipedia freeIPA is an open source project sponsored by Red Hat that aims to provide an easily managed Identity, Policy and Audit (IPA) suite primarily targeted towards networks of Linux and Unix computers. FreeIPA aims to provide support not just for Linux- and Unix-based computers, but  for Microsoft Windows and Apple OS X computers as well.

FreeIPA server offers a web API that possibilits interaction with the server. I wrote a PHP library for connection with it and published as a free software in the Github. The following lines are a guide to use it.

Installation

The best way to install is through composer, as below:

php composer.phar require gnumoksha/php-freeipa

However it is also possible to install through clonning the Github repository or download zip file.

Basic Usage

First, it is necessary to obtain the server certificate. You can access https://server/ipa/config/ca.crt with your browser and save the file or use some cli software. Example:

wget --no-check-certificate https://ipa.demo1.freeipa.org/ipa/config/ca.crt -O vendor/gnumoksha/php-freeipa/certs/ipa.demo1.freeipa.org_ca.crt

Now you need include the autoload:

// For use with composer
require_once('vendor/autoload.php');
// For other use types
//require_once('src/autoload.php');

Creates a new instance of class with the server address and full path for the certificate file:

$host = 'ipa.demo1.freeipa.org';
$certificate = 'vendor/gnumoksha/php-freeipa/certs/ipa.demo1.freeipa.org_ca.crt';
try {
    $ipa = new \FreeIPA\APIAccess\Main($host, $certificate);
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

And make login

$user = 'admin';
$password = 'Secret123';
try {
    $auth = $ipa->connection()->authenticate($user, $password);
    if ($auth) {
        print 'Logged in';
    } else {
        $auth_info = $ipa->connection()->getAuthenticationInfo();
        var_dump($auth_info);
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

Example of $auth_info in case of error:

array(4) {
  ["authenticate"]=>
  bool(false)
  ["reason"]=>
  string(16) "invalid-password"
  ["message"]=>
  string(28) "User or password are wrong. "
  ["http_code"]=>
  int(401)
}

And success:

array(4) {
  ["authenticate"]=>
  bool(true)
  ["reason"]=>
  bool(false)
  ["message"]=>
  string(37) "User has successfully authenticated. "
  ["http_code"]=>
  int(200)
}

Managing users

You can get all information about one user:

try {
    $user_info = $ipa->user()->get('admin');
    var_dump($user_info);
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

Output example:

object(stdClass)#9 (25) {
  ["cn"]=>
  array(1) {
    [0]=>
    string(13) "Administrator"
  }
  ["dn"]=>
  string(57) "uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org"
  ["gecos"]=>
  array(1) {
    [0]=>
    string(13) "Administrator"
  }
  ["gidnumber"]=>
  array(1) {
    [0]=>
    string(10) "1120000000"
  }
  ["has_keytab"]=>
  bool(true)
  ["has_password"]=>
  bool(true)
  ["homedirectory"]=>
  array(1) {
    [0]=>
    string(11) "/home/admin"
  }
  ["ipantsecurityidentifier"]=>
  array(1) {
    [0]=>
    string(44) "S-1-5-21-3620654872-687157142-4050297923-500"
  }
  ["ipauniqueid"]=>
  array(1) {
    [0]=>
    string(36) "8ac17c74-ebd3-11e3-8b94-fa163e91f9c8"
  }
  ["krbextradata"]=>
  array(1) {
    [0]=>
    object(stdClass)#10 (1) {
      ["__base64__"]=>
      string(48) "AAIp71NWcm9vdC9hZG1pbkBERU1PMS5GUkVFSVBBLk9SRwA="
    }
  }
  ["krblastfailedauth"]=>
  array(1) {
    [0]=>
    string(15) "20151124084835Z"
  }
  ["krblastpwdchange"]=>
  array(1) {
    [0]=>
    string(15) "20151124050129Z"
  }
  ["krblastsuccessfulauth"]=>
  array(1) {
    [0]=>
    string(15) "20151124090527Z"
  }
  ["krbloginfailedcount"]=>
  array(1) {
    [0]=>
    string(1) "0"
  }
  ["krbpasswordexpiration"]=>
  array(1) {
    [0]=>
    string(15) "20161123050129Z"
  }
  ["krbprincipalname"]=>
  array(1) {
    [0]=>
    string(23) "admin@DEMO1.FREEIPA.ORG"
  }
  ["krbticketflags"]=>
  array(1) {
    [0]=>
    string(3) "128"
  }
  ["loginshell"]=>
  array(1) {
    [0]=>
    string(9) "/bin/bash"
  }
  ["memberof_group"]=>
  array(2) {
    [0]=>
    string(6) "admins"
    [1]=>
    string(12) "trust admins"
  }
  ["nsaccountlock"]=>
  bool(false)
  ["objectclass"]=>
  array(10) {
    [0]=>
    string(20) "ipaSshGroupOfPubKeys"
    [1]=>
    string(9) "ipaobject"
    [2]=>
    string(14) "ipaNTUserAttrs"
    [3]=>
    string(3) "top"
    [4]=>
    string(10) "ipasshuser"
    [5]=>
    string(6) "person"
    [6]=>
    string(18) "krbticketpolicyaux"
    [7]=>
    string(15) "krbprincipalaux"
    [8]=>
    string(8) "inetuser"
    [9]=>
    string(12) "posixaccount"
  }
  ["preserved"]=>
  bool(false)
  ["sn"]=>
  array(1) {
    [0]=>
    string(13) "Administrator"
  }
  ["uid"]=>
  array(1) {
    [0]=>
    string(5) "admin"
  }
  ["uidnumber"]=>
  array(1) {
    [0]=>
    string(10) "1120000000"
  }
}

Or groups in which the user is:

try {
    $user_info = $ipa->user()->get('admin');
    if (isset($user_info->memberof_group)) {
        foreach($user_info->memberof_group as $group) {
            print $group . PHP_EOL;
        }
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

You can search user through find() method

// search in login, first_name and last_name fields.
try {
    $users = $ipa->user()->find('admin');
    if ($users) {
        foreach($users as $user) {
            print $user->uid[0];
         }
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

// search by users that are in group 'admins'
try {
    $users = $ipa->user()->find(array(), array('in_group' => 'admins'));
    if ($users) {
        foreach($users as $user) {
            print $user->uid[0];
         }
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

Or use the method findBy which is easier

// search by users that are in group 'admins'
try {
    $users = $ipa->user()->findBy('in_group', 'admins');
    if ($users) {
        foreach($users as $user) {
            print $user->uid[0] . PHP_EOL;
         }
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

// Search by e-mail
try {
    $users = $ipa->user()->findBy('mail', 'manager@demo1.freeipa.org');
    if ($users) {
        foreach($users as $user) {
            print $user->uid[0];
         }
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

You can insert a user

try {
    $new_user_data = array(
        'givenname' => 'Richard',
        'sn' => 'Stallman',
        'uid' => "stallman",
        'mail' => "rms@fsf.org",
        'userpassword' => 'Secret123',
    );

    $add_user = $ipa->user()->add($new_user_data);
    if ($add_user) {
        print 'User added' . PHP_EOL;
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

And modify it:

try {
    $new_user_data = array(
        'sn' => 'Matthew Stallman',
    );

    $mod_user = $ipa->user()->modify('stallman', $new_user_data);
    if ($mod_user) {
        print 'User modified' . PHP_EOL;
    }
} catch (Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

Managing groups

Adding a group

try {
    $add_group = $ipa->group()->add("activists", "People who change the world");
    if ($add_group) {
        print('Group added');
    }
} catch (\Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

And put users, or other groups, in:

try {
    $add_group = $ipa->group()->addMember("activists", "stallman");
    if ($add_group) {
        print('User added in group');
    }
} catch (\Exception $e) {
    print("Error {$e->getCode()}: {$e->getMessage()}");
}

For more information and examples, see the repositório.

Over time new features will be added. If you have suggestions, even features, leave a comment.