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'});

Greetings
Oliver

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:
Hi,

i've tried user_mod instead because of
https://docs.fedoraproject.org/en-US/Fedora/18/html/FreeIPA_Guide/pwd-expiration.html
and got

Error-code:    2100
Error-name:    ACIError
Error-msg:    Insufficient access: Insufficient 'write' privilege to
the 'krbPasswordExpiration' attribute of entry
'uid=k812339,cn=users,cn=accounts,dc=kreditwerk,dc=de'.

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

[09/Nov/2015:18:40:31 +0100] conn=658 op=7 MOD
dn="uid=k812339,cn=users,cn=accounts,dc=kreditwerk,dc=de"
[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

Content-Type:application/x-www-form-urlencoded

and e.g.:

user:bbar
old_password:a
new_password:b

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
Oliver

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

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","addattr":"krbpasswordexpiration=20160207010919Z","cn":"Oliver
Support","sn":"Support"}],"id":0,"method":"user_add"}


{"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?

Thanks
Oliver


--
Manage your subscription for the Freeipa-users mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-users
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";


BEGIN {
};


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

        bless($self,$Class);
        $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')

        $ipaObj->{$scalar}=$value;
}       # 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' => 
$paramRef->{'newPassword'}});
        $client->setHost($ipaObj->{'baseUrl'});
        $client->POST("/ipa/session/change_password", substr($params,1), 
$headers);
        
        # Change was not succesful
        if ($client->responseCode() != 200) {
                $ipaObj->{"errCode"} = $client->responseCode();
                $ipaObj->{"errName"} = "HTTP error";
                $ipaObj->{"errMsg"} = $client->responseContent();
                $ipaObj->error();
        } 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();
                        $ipaObj->error();
                }       # 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 
        $ipaParam->{'uid'}=$paramRef->{'uid'};
        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->setHost($ipaObj->{'baseUrl'});
        $client->POST("/ipa/session/login_password", substr($params,1), 
$headers);
        
        # Login was not succesful
        if ($client->responseCode() != 200) {
                $ipaObj->{"errCode"} = $client->responseCode();
                $ipaObj->{"errName"} = "HTTP error";
                $ipaObj->{"errMsg"} = $client->responseContent();
                $ipaObj->error();
        } else {
                $ipaObj->{'authCookie'} = $client->responseHeader('Set-Cookie');
                $ipaObj->{'restClient'}=$client;
        }       # 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 = {
                'id'=>$ipaObj->{'id'},
                'params' => [
                                                [],
                                                $paramHash
                                        ]
        };      # 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"; }
        $ipaObj->{'restClient'}->POST("/ipa/session/json", 
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'};
                $ipaObj->error();
        }       # if ($restRet->{"error"})
        # ... and return these
        return $restRet;
}       # sub ipaMethod
-- 
Manage your subscription for the Freeipa-users mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-users
Go to http://freeipa.org for more info on the project

Reply via email to