Hi Petr,

thanks for your hint. It works now. I've decided to change first the password to a random pasword as admin using user_mod and afterwards my code is using ipa/session/change_password to set the password to the final one.

So I added this to my Perl module and I'm calling the code using...
$ipaClient->changePasswordAsAdmin({'uid' =>'k812339', 'newPassword' => 'start123', 'doNotExpire' => 'true'});


Am 12.11.2015 um 13:29 schrieb Petr Vobornik:
On 11/11/2015 04:13 PM, Alexander Bokovoy wrote:
On Wed, 11 Nov 2015, Oliver Dörr wrote:

i've tried user_mod instead because of
and got

Error-code:    2100
Error-name:    ACIError
Error-msg:    Insufficient access: Insufficient 'write' privilege to
the 'krbPasswordExpiration' attribute of entry

Inside the acces log of the LDAP Server I could see...

[09/Nov/2015:18:40:31 +0100] conn=658 op=7 MOD
[09/Nov/2015:18:40:31 +0100] conn=658 op=7 RESULT err=50 tag=103
nentries=0 etime=0

So it looks like it is a permission issue. But I still have the
problem when use admin to do the job. Any idea about how to change the
permission or an API that it is able to do the job?
You simply cannot make it working for cases when a password change
coming from a non-user. This is intentional.

See http://www.freeipa.org/page/New_Passwords_Expired

You can do double change via LDAP password change (or Kerberos) where
you changre a
password first to something temporary, then try to change it again as a
user with that temporary password and set a new one. Since the second
change would be done as a user, that should allow the change to happen
without raising a flag.

You can use ipa/session/change_password call for that. With


and e.g.:


Web UI uses it when user with expired password is resetting his pw. So you can check the communication in browser network tab.

Thanks in advance

Am 11.11.2015 um 15:29 schrieb Oliver Dörr:

i'm still working with the JSON API and I now have the problem, that
I want to add a user with a not expired password. I've tried setattr
and addattr with the following JSON code, but both fail.

{"params":[[],{"givenname":"Oliver","userpassword":"start123","uid":"k812339","version":"2.151","cn":"Oliver Support","setattr":"krbpasswordexpiration=20160207010919Z","sn":"Support"}],"id":0,"method":"user_add"}

The user is added to IPA, but the user is still forced to change it's
password. In the response I could see that  my krbpasswordexpiration
is ignored.

Any ideas what I'm doing wrong?


Manage your subscription for the Freeipa-users mailing list:
Go to http://freeipa.org for more info on the project

package freeipa;

use strict;
use REST::Client;
use JSON;
use Encode;
use Data::Dumper;

our $VERSION="0.0.2";


sub new
# Constructor of the class freeipa
{       my ($Class)=@_;
        my $self= {};

        $self->{'id'}=0;        # id is a unique numeric identifier for the 
product. Red Hat uses 0.
        return $self;
}       # sub news

sub set
# Setter of the class freeipa. At this moment only usuable or scalar values 
{       my $ipaObj=shift;
        my $scalar=shift;
        my $value=shift;
        # Should we use the API-version from the server environment ?
        if ($scalar eq 'version' && $value eq 'env') {
                my $retObj=$ipaObj->ipaMethod({'method' => 'env'});
                if (! $retObj->{'error'} && 
($retObj->{'result'}->{'result'}->{'api_version'})) { 
$value=$retObj->{'result'}->{'result'}->{'api_version'}; }
        }       # if ($scalar eq 'version' && $value eq 'env')

}       # sub set

sub error
# This method prints out the error messages and exit 1 if configured.
{       my $ipaObj=shift;

        print "Error-code:\t".$ipaObj->{"errCode"}."\n";
        print "Error-name:\t".$ipaObj->{"errName"}."\n";
        print "Error-msg:\t".$ipaObj->{"errMsg"}."\n";
        if ($ipaObj->{'dieOnError'}) { exit 1; }
}       # sub error

sub changePasswordAsUser
# Connects to the specified IPA server via REST and changes the password of the 
specified user.
# You have to provide the old and the new password
{       my $ipaObj=shift;
        my $paramRef=shift;

        my $headers = {
                'Accept' => 'text/plain',
                'Content-Type' => 'application/x-www-form-urlencoded',
                'Referer' => $ipaObj->{'baseUrl'}
        };      # my $headers
        my $client=REST::Client->new();
        my $params = $client->buildQuery({'user' => $paramRef->{'uid'}, 
'old_password' => $paramRef->{'oldPassword'}, 'new_password' => 
        $client->POST("/ipa/session/change_password", substr($params,1), 
        # Change was not succesful
        if ($client->responseCode() != 200) {
                $ipaObj->{"errCode"} = $client->responseCode();
                $ipaObj->{"errName"} = "HTTP error";
                $ipaObj->{"errMsg"} = $client->responseContent();
        } else {
                # Policy violations also have the responseCode == 200 and so we 
have to take a closer look
                if ($client->responseContent() =~ /rejected/) {
                        $ipaObj->{"errCode"} = $client->responseCode();
                        $ipaObj->{"errName"} = "Policy violation";
                        $ipaObj->{"errMsg"} = $client->responseContent();
                }       # if ($client->responseContent() =~ /rejected/)
        }       # if ($client->responseCode() != 200)
}       # sub changePasswordAsUser

sub changePasswordAsAdmin
# Connects to the specified IAP server via REST/JSON as an admin and
# sets the password of the user. You need to specifiy uid and an optional
# new password. There is a randon password generated, if you do not sepcify
# a new one. Using the option 'doNotExpire' you could get a password that
# is not expred. Please notice that the IPA  will set the new password to
# expired, if doNotExpire is not specified.
{       my $ipaClient=shift;
        my $paramRef=shift;
        my $ipaParam={};
        my $newPassword=$paramRef->{'newPassword'};
        my $oldPassword=$newPassword;

        # Set the new password either well by the caller or random 
        if ($newPassword && ! $paramRef->{'doNotExpire'}) 
{$ipaParam->{'userpassword'}=$newPassword} else { $ipaParam->{'random'}="true"; 
        my $retObj=$ipaClient->ipaMethod({'method' => 'user_mod'}, $ipaParam);
        if ($ipaParam->{'random'}) { 
$oldPassword=$retObj->{'result'}->{'result'}->{'randompassword'}; }
        # The password should not be expired and so we have to change it as user
        if ($paramRef->{'doNotExpire'}) {
                $ipaClient->changePasswordAsUser({'uid' =>$paramRef->{'uid'}, 
'oldPassword'=>$oldPassword, 'newPassword'=>$newPassword});
        return $retObj->{'result'}->{'result'}->{'randompassword'};
}       # sub changePasswordAsAdmin

sub connect
# Connects to the specified IPA server
{       my $ipaObj=shift;
        my $headers = {
                'Accept' => 'text/plain',
                'Content-Type' => 'application/x-www-form-urlencoded',
                'Referer' => $ipaObj->{'baseUrl'}
        };      # my $headers
        my $client=REST::Client->new();
        my $params = $client->buildQuery({'user' => $ipaObj->{'user'}, 
'password' => $ipaObj->{'password'} });
        $client->POST("/ipa/session/login_password", substr($params,1), 
        # Login was not succesful
        if ($client->responseCode() != 200) {
                $ipaObj->{"errCode"} = $client->responseCode();
                $ipaObj->{"errName"} = "HTTP error";
                $ipaObj->{"errMsg"} = $client->responseContent();
        } else {
                $ipaObj->{'authCookie'} = $client->responseHeader('Set-Cookie');
        }       # if ($client->responseCode() != 200)
}       # sub connect

sub ipaMethod
# Calls an API method against the IPA connection
{       my $ipaObj=shift;
        my $hashRef=shift;
        my $paramRef=shift;
        # create the parameter hash for the API call, version will be filled by 
default, all others
        # came from the parameter reference that we got by calling the ipaMethod
        my $paramHash={};
        if ($ipaObj->{'version'}) { $paramHash = { 'version' => 
$ipaObj->{'version'} }; }
        foreach my $param (keys (%{$paramRef})) { $paramHash->{$param} = 
$paramRef->{$param}; }
        # We need data and header for the JSON request against the IPA API
        my $data = {
                'params' => [
        };      # my $data
        my $headers = {
                'Accept' => 'text/plain',
                'Content-Type' => 'application/json',
                'Cookie' => $ipaObj->{'authCookie'},
                'Referer' => $ipaObj->{'baseUrl'}."/ipa/session/json"
        # Copy the specified part of the method over the default data defined 
in $data
        foreach my $var (keys (%{$hashRef})) { $data->{$var}=$hashRef->{$var}; }
        # Format the method and data to json and make a REST request against 
the IPA server
        my $jsonRequest = encode_json($data);
        if ($ipaObj->{'debug'}->{'printJsonRequest'}) { print "JSON-Request: 
".$jsonRequest."\n"; }
decode("utf8",$jsonRequest), $headers);
        # bring the JSON-formed response into perl objects...
        my $jsonReponse = $ipaObj->{'restClient'}->responseContent();
        if ($ipaObj->{'debug'}->{'printJsonResponse'}) { print "JSON-Response: 
".$jsonReponse."\n"; }
        my $restRet=decode_json($jsonReponse);
        # Minimal error handling
        if ($restRet->{"error"}) {
                $ipaObj->{"errCode"} = $restRet->{"error"}->{"code"};
                $ipaObj->{"errMsg"} = $restRet->{"error"}->{'message'};
                $ipaObj->{"errName"} = $restRet->{"error"}->{'name'};
        }       # if ($restRet->{"error"})
        # ... and return these
        return $restRet;
}       # sub ipaMethod
Manage your subscription for the Freeipa-users mailing list:
Go to http://freeipa.org for more info on the project

Reply via email to