Repository navigation
Releases: neverlless/goipa
Release list
v1.1.0
Added
- Host writes:
HostAdd(random one-time password,force),
HostAddWithPassword,HostMod,HostDelete(updatedns) and
HostDisable, with…Contexttwins;Host.RandomPassword StageUserAddWithPasswordsets the initial password onstageuser_add
(#14)WithTruncationErrors():UserFind,GroupFind,HostFind,
StageUserFind,SubIDFind,FetchOTPTokens,HBACRuleFindand
SudoRuleFindreturnErrTruncatedwith the entries they got; the
default stays silent as in v1.0 (#15)- Examples for
WithHTTPClient(timing the requests) andHostAdd - Kerberos documented: SPNEGO on the first call, then the
ipa_session
cookie;LoginFromCCachetakes the path of a file cache (notKCM:; strip
aFILE:prefix fromKRB5CCNAME); afterStickySession(false)every call
negotiates SPNEGO ipatest:Server.GrantPrivilege(uid, privilege)gives a user one FreeIPA
privilege, for tests of delegated rights (#18)
Changed
ipatest:Calls()now redacts passwords (userpasswordand the like)
in the recorded options, so tests that asserted the raw values must
compare"REDACTED"(the server state keeps the password)ipatest: password changes by the user now enforce the user's effective
policy (group policies by priority, character classes, history) and the
minimum lifetime. A second self-change withinMinLife(1 h by default)
is refused; tests that change a password twice should callSetPwPolicy
withMinLife0 (users seeded withAddUserare exempt for their first
change) (#19, Q180 to Q183)ipatest: a malformedkrbpasswordexpirationis refused (3008
ConversionError, as FreeIPA) instead of meaning "never expires" (Q184)ipatest:hbacrule_find,sudorule_find,subid_findand
otptoken_findhonoursizelimit(Q165 to Q167)ipatest: a caller outsideadminswho holds no granted privilege gets
2100ACIError(ErrACI) onuser_add,user_mod(other users),
user_del,stageuser_add,group_add/_mod/_del,
host_add/_mod/_del,hostgroup_add/_del,service_add/_del,
hbacrule_add/_enable/_disable/_del,sudorule_add/_del,dnszone_addand
automember_add, as FreeIPA 4.13.4 does on every release. The message
followsSetVersion: the API permission text, or the directory's ACI text
from 4.10 up to 4.13.3.user_modon the caller's own entry stays allowed
for self-service attributes. The checks of Q24, Q32, Q95 and Q122 also pass
with the matching granted privilege. Tests that wrote as a plain user must
useadminorGrantPrivilege(Q168 to Q174). Not modelled: the 4001 a
plain user gets fromdnsrecord_add(Q171) and 4.13.4 refusing an own
passkey add (Q172)ipatest:host_add,host_mod,host_disableandhost_delwith
updatedns(which removes the host's A and AAAA records, Q158); macaddress
comes back upper-case (Q156);host_disablefollows the real server's
keytab rules (Q157)ipatest:user_addandstageuser_addwithuserpasswordkeep it,
expired;stageuser_activatecarries it over (Q160, #16);user_mod
acceptssetattr krbPasswordExpirationto lift the expiry (#17)
v1.0.0
The v1 API freeze: from v1.0.0 no exported identifier of ipa or ipatest
is removed or re-signed (see Stability in the README). This release marks
what newer identifiers supersede, fixes the last client-side bugs found in
the API review and makes ipatest follow FreeIPA more closely.
Deprecated
NewDefaultClient,NewDefaultClientWithSession,NewClientand
NewClientCustomHttp(useNew),DefaultTOTPToken(useAddOTPToken
with nil),ParseDateTime(useEntry.Time) andResponse.Error. All
keep working.
Added
ipatest: gettersHBACRule,SudoRule,PwPolicy,Role,Privilege
andPermission, andService.AuthIndicators
Changed
- Wire-equivalent shape changes, visible in
ipatest.Calls():
hbacrule_delanddnszone_delsendcontinue: false;
hostgroup_findandotptoken_findwith no criteria send[""]as the
argument Entry.Strsreturns a lone hint object other than__dns_name__as its
JSON instead of its inner value, as it already did inside a list- A 401 from
SetPasswordandSyncOTPTokennow also matches
ErrUnauthorized; failures ofRemoteLogin,SetPasswordand
SyncOTPTokenmatch*HTTPErrorwitherrors.As, message text unchanged - With
WithValidation, an option key that names a positional argument newer
than the server givesErrNotSupported ipatestbehaviour (see Q140 to Q155 in the package documentation):
host_deldeletes the host's services; host group cycles are accepted;
service_modandkrbprincipalauthind;sudoordermust be unique and
sudo rules reject member lists that conflict with a category;hbactest
expands the default HBAC service groups; RBACcnfinds match the whole
name;otptoken_delby a non-admin gives 2100; certificate principals are
case-sensitive and a second revoke fails; DNS apex and name checks;
session_logoutdoes not end the session, as on real servers (Q155), and
a missing session gets FreeIPA's HTML 401 page
Fixed
- A goroutine waiting for another's password re-login returns
ctx.Err()
when its context ends instead of blocking ClearSessionduring a re-login is no longer undone by the login that was
already in flight- Command catalogue generator:
autofillis read only as a keyword argument,
a stale allow-list entry and two source files for one version are errors
Security
- On FreeIPA (seen on 4.9.13, 4.12.2 and 4.13.4) the server keeps accepting a session cookie after
session_logout. Logout only makes the client forget it, so treat a
session ID as a credential until it expires. Documented in the README and
the package documentation.
v0.9.1
Fixed
ipatest: host group names are matched case-insensitively in rules,
services, automember rules and nested groups, as in FreeIPA, and are
reported lower-cased
v0.9.0
Typed objects: host groups, services and keytab access, HBAC and sudo rule
management, certificates, DNS zones and records, automember rules, and
roles, privileges and permissions, each with an ipatest model and contract
tests checked against real FreeIPA 4.9, 4.12 and 4.13. ipatest also
answers commands it does not model with responses recorded from those
servers.
Added
- Host groups:
HostGroupShow,HostGroupFind,HostGroupAdd,
HostGroupDelete, member and member-manager calls - Services:
ServiceShow,ServiceFind,ServiceAdd,ServiceDelete,
ServiceDisable, hosts that manage a service, and the keytab access lists
(ServiceAllowRetrieveKeytaband its three siblings withKeytabAccess) - HBAC and sudo rules: show, add, delete, enable, disable and members
(HBACRuleAddUser,SudoRuleAddAllowCommand,SudoRuleAddRunAsUser,
SudoRuleAddOption, ...);SudoRule.RunAsUserGroups - Certificates:
CertRequest,CertShow,CertRevoke - DNS: zones (
DNSZoneShow,DNSZoneFind,DNSZoneAdd,DNSZoneDelete,
DNSZoneEnable,DNSZoneDisable) and records (DNSRecordShow,
DNSRecordFind,DNSRecordAdd,DNSRecordRemove,DNSRecordDelete) - Automember rules: show, find, add, delete, conditions, default group,
rebuild (AutomemberShow,AutomemberAddCondition,AutomemberRebuild, ...) - Roles, privileges and permissions, read only:
RoleShow/RoleFind,
PrivilegeShow/PrivilegeFind,PermissionShow/PermissionFind - Every new call has a
...Contexttwin. Attribute changes go through
Modify(for automember,RPC, since it needs the rule type); member
calls return the updated object and a*MemberErrorfor members the
server refused ipatest: models for all of the above, withAddHostGroup,AddService,
AddRole,AddPrivilegeandAddPermissionseed helpers (AddHBACRule
andAddSudoRuleexist since v0.5.0)ipatest:NewRecorderrecords a real server's*_show/*_find
responses (secrets redacted) andServer.SetReplayanswers from them; the
recordings of FreeIPA 4.9.13, 4.12.2 and 4.13.4 are embedded, so tests of
commands goipa does not wrap see real response shapes.IPATEST_RECORD=dir
records during the contract tests
Changed
ipatest:host_addandhost_delare modelled;host_deland
hostgroup_delremove the deleted entry from host groups, HBAC and sudo
rules and services that named itipatest:sudorule_add_user(and the other sudo member calls) with
unknown users, groups or hosts now succeeds, keeping them as external
members as FreeIPA does; a duplicatesudorule_add_optionis 4002ipatest: commands that are not modelled are checked against the
catalogue too, so an unknown option is 3005 before the 905 or replayed
answeripatest: a*_showor*_findcommand that is not modelled and has no
Handleoverride is answered from the recordings instead of 905 (a
built-in or aHandleoverride still wins);SetReplay(nil)restores 905.
The recordings add about 3 MB to theipatestpackage only- The integration CI container installs FreeIPA with integrated DNS
Notes from the real servers
Checked on FreeIPA 4.9.13, 4.12.2 and 4.13.4; ipatest follows them
(quirks Q50 to Q139 in its documentation).
- Enabling or disabling an HBAC rule, sudo rule or DNS zone twice succeeds
- The default certificate profile accepts RSA keys only; an ECDSA CSR fails
- On 4.9
sudorule_add_optiontakes one option per request, so
SudoRuleAddOptionsends them one at a time - A sudo rule's unknown users, groups and hosts become external members
v0.8.0
Command catalogue: every command, argument and option of FreeIPA 4.9.0 to
4.13.4, with the release that introduced each, generated from FreeIPA's own
API.txt. Clients can opt in to checking every call against it before it
is sent. Checked against real FreeIPA 4.9, 4.12 and 4.13 by the contract
tests, which now run with validation on.
Added
Commands,LookupCommand,CommandandParam: the FreeIPA command
catalogue for releases 4.9.0 to 4.13.4 (positional arguments, options,
types and the release that introduced each), generated fromAPI.txtwith
go generate; a nightly CI job fails when it is out of dateWithValidationandErrInvalidCall: opt-in check of every call against
the catalogue before it is sent, including each call insideBatch;
commands and options newer than the server giveErrNotSupportedipatest: built-in commands reject options the command lacks at the
reported release (OptionError) and commands added after it;
passkeyconfig_showis modelled
Changed
ipatest: built-in commands now reject options they lack and commands
newer than theSetVersionrelease (3005 / 905), so consumer tests that
sent such options may fail on upgrade;SetVersionnow affects behaviour,
not only the reported string.Handleoverrides are not checked
v0.7.0
Typed escape hatch and core API: any FreeIPA command can be called with
typed decoding, truncated searches are reported, attributes can be changed
one at a time, several commands can run in one round trip, and calls for
features newer than the server fail early. Checked against real FreeIPA
4.9, 4.12 and 4.13 by the contract tests.
Added
Call[T], a generic typed call for any FreeIPA command, andEntry, a
result object withHas,Str,Strs,Bool,Int,Time,Bytes,
DNandRawaccessors that read FreeIPA's attribute lists,
__datetime__and__base64__valuesFindEntries(ctx, c, method, args, opts, sizelimit)andErrTruncated:
a*_findthat reports a result truncated by the server's size limit
instead of returning it silentlyServerVersionandErrNotSupported: passkey calls (FreeIPA 4.11) and
SubIDFind/SubIDGenerate(4.9.7) fail before sending when the known
server is olderModify(command, keys...):setattr/addattr/delattrupdates of
single attributes on any object, nested ones includedBatch: several commands in one round trip with per-command results;
BatchResult.Erris anerrorholding a bare*IpaErrorCodeConversion(3008),CodeObjectclassViolation(4205) andCodeOnlyOneValueAllowed(4207)ipatest:SetVersion,sizelimittruncation onuser_find,
group_findandhost_find,setattr/addattr/delattronuser_mod
andstageuser_mod(includingOnlyOneValueAllowed), andbatch
v0.6.0
Construction and authentication: an options-based New with no file I/O at
import time, Kerberos login from memory, WhoAmI, and recovery from expired
sessions. The session behaviour is checked against real FreeIPA 4.9, 4.12
and 4.13 by the contract tests.
Added
New(opts ...Option) (*Client, error)withWithHost,WithRealm,
WithCACert,WithHTTPClient,WithKrb5Config,WithKrb5ConfigDataand
WithPasswordRelogin. The old constructors keep their signaturesLoginWithKeytabData,LoginFromCCacheDataand in-memory Kerberos
configuration (WithKrb5ConfigData; idea from sitnikovv's fork), for
containers and secret storesWhoAmIandWhoAmIContext- Expired sessions are recovered: Kerberos clients retry once through
SPNEGO; withWithPasswordRelogin,RemoteLoginclients log in again
and retry once (a password FreeIPA rejects is forgotten; needs sticky
sessions; concurrent 401s cost one login). Other clients get
ErrUnauthorizedand the session is cleared ipatest.Server.CACert, andwhoamiandsession_logoutinipatest- "Which login to use" guide in the README and package documentation
Changed
- A 401 on a session request now clears the session (it was kept)
- Clients with a Kerberos login, old constructors included, retry once
through SPNEGO after a 401 NewDefaultClient*,NewClientandNewread/etc/ipaon first use
instead of at import;NewClientCustomHttpnever reads itClearSessionalso forgets the credentials kept byWithPasswordRelogin- FreeIPA's logout cookie (an
ipa_sessioncookie that deletes the session,
orMagBearerToken=) clears the session; before,session_logoutfailed
with "invalid set-cookie header"
v0.5.0
Account lifecycle and access: stage users, lockout status and unlock,
password policy, subordinate IDs, HBAC and sudo rules with hbactest,
passkey mappings and OTP token sync, each with a Context twin and an
ipatest model. Every behaviour is checked against real FreeIPA 4.9,
4.12 and 4.13 by the contract tests.
- Stage users:
StageUserAdd,StageUserShow,StageUserFind,
StageUserMod,StageUserActivateandStageUserDelete - Lockout:
UserStatusreturns oneReplicaStatusper master (failed
logins in either of FreeIPA's forms, last success and failure times, an
unreachable master reported instead of failing the call);UserUnlock - Password policy:
PwPolicyShowandUserPwPolicy, with durations as
time.Durationand the FreeIPA 4.13 password-quality credits and grace
login limit - Subordinate IDs:
SubIDFindandSubIDGenerate - HBAC and sudo:
HBACRuleFind,SudoRuleFindandHBACTest, which
reads hbactest's result correctly and evaluates every rule, not only the
first 100 - Passkeys:
UserAddPasskeyandUserRemovePasskey SyncOTPTokenandErrInvalidCredentials(based on ubccr/goipa#2 by
@farzandalaee)CodeOption(3005 OptionError: an option the command does not take)ipatestmodels stage users, user_status and user_unlock, password
policies, sub-IDs, HBAC and sudo rules (with the defaultallow_all
rule), hbactest, passkey mappings and token sync
v0.4.0
Users and groups: typed group management with per-member failures as
errors, all of a user's mail addresses, address, language and passkeys,
and host lookups. Every behaviour is checked against real FreeIPA 4.9,
4.12 and 4.13 by the contract tests.
- Groups:
GroupShow,GroupFind,GroupAdd,GroupMod,GroupDelete,
GroupAddMember,GroupRemoveMember,GroupAddMemberManagerand
GroupRemoveMemberManager, each with aContexttwin. Per-member
failures, including insufficient access, are returned as*MemberError
(FreeIPA reports them with no error); the updated group is returned with
it. Based on ubccr/goipa#9 by @earthquakesan, #14 by @ivanovilia96 and
#17 by @m-vinc User.Emails(allmailvalues, ubccr/goipa#10),IndirectGroups
(fromuser_show; idea from fajo-de),Street,City,State,
PostalCode,PreferredLanguage,Title,OrgUnit(title/ou as in
tubby1981's fork) andPasskeys. These are read-only:UserModdoes
not write themHostShowandHostFind(ubccr/goipa#11)ipatestmodels groups, member managers, nested groups, hosts and the
new user attributes in FreeIPA's response shapes; contract tests pin
them against the real server in the nightly runUserModdropped everymailvalue but the first.Emailis still the
first address and replaces it; the rest ofEmailsis kept. A single
address is sent exactly as beforeSetPasswordno longer posts an emptyotpfield;randompasswordis
read whether the server returns a string or a list (both found by
tubby1981)
v0.3.0
Test infrastructure: an in-memory FreeIPA server for unit tests, and the
same contract tests run nightly against real FreeIPA 4.9, 4.12 and 4.13.
The first real-server runs found a bug in UserAdd that dates back to
ubccr/goipa v0.0.7; it is fixed here.
- New package
ipatest: a fake FreeIPA server over TLS for tests of code
that uses goipa.NewServer(t)(orNew()outside tests),Client,
ClientAs,Session, seed and inspect users and OTP tokens, a call
log (Calls) andHandleto inject errors or serve any command it
does not model. It models user_show/find/add/mod/del/disable/enable,
passwd, otptoken_add/del/mod/find, login_password and change_password
with the lockout, expiry and last-OTP-token behaviour of FreeIPA 4.13;
each quirk is listed in the package doc and pinned by a test (*IpaError).MarshalJSONwrites FreeIPA's error shape
(code,message,name,data);Datathat is not JSON becomes{}- Unit tests for the whole API against
ipatest, coverage above 80 %
(gated in CI) and Codecov upload - Integration tests run nightly against FreeIPA 4.9.13, 4.12.2 and 4.13.4;
the same contract tests run againstipatestand the real server. The
integration tests are now named*_integration_test.go - pkg.go.dev examples for the login modes and the
RPCescape hatch - Removed the CentOS 7
container/,docker-compose.ymland.env.sample;
scripts/ipa-up.shstarts a FreeIPA container instead - Testing with
ipatest: it answers/ipa/json(the Kerberos endpoint)
with 401 unlessSetNegotiateUseris set, as a real server does for a
client without a Kerberos ticket; log in withRemoteLoginorClientAs
instead UserAddandUserAddWithPasswordleave empty attributes out of
user_add, so FreeIPA applies its defaults; an unsetHomeDirfailed
with 4205 missing attribute "homeDirectory" (bug since v0.0.7)ipatest: JSON-RPC without a valid Referer gets HTTP 400 text/html like
FreeIPA, not error 911; aMagBearerTokenit did not issue closes the
connection (goipa returns EOF), as the real server's httpd crashes on itipatestmodels user_add with an empty homedirectory (4205, Q19)ipatest.Server.ExpireSessionends a session; calls with it get 401
(ErrUnauthorized), as for an expired session on FreeIPAscripts/ipa-up.shsetsforwardable = truein krb5.conf; without it
every Kerberos call fails 2100 "Credential cache is empty"- Contract tests expect invalid-password for locked users before FreeIPA
4.13.1 (FreeIPA issue 9891)