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