Help us shape the future of Go! Take the 2026 Go Developer Survey

ipa

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: BSD-3-Clause Imports: 31 Imported by: 1

README

goipa

Go client library for the FreeIPA / Red Hat IdM JSON-RPC API.

CI Coverage Go Reference Release Go Report Card Go version License

goipa talks to a FreeIPA server over HTTPS using its JSON-RPC API. It logs in with a password, a keytab, a Kerberos credential cache or an existing session, and gives you typed Go calls for users, stage users, groups with their members and member managers, hosts, passwords and lockout, password policy, sub-IDs, HBAC/sudo rules and hbactest, passkeys and OTP tokens.

Note: This is the maintained continuation of ubccr/goipa by Andrew E. Bruno, which has had no release since 2024. It is a drop-in replacement for ubccr/goipa v0.0.7; see Migrating from ubccr/goipa. It is developed alongside mokey, a FreeIPA self-service portal.

Features

  • Login: password (Login, RemoteLogin), keytab (LoginWithKeytab, LoginWithKeytabData), Kerberos credential cache (LoginFromCCache, LoginFromCCacheData), or a saved session ID (SetSessionID); see Which login to use
  • Kerberos clients recover expired sessions; password re-login is opt-in (WithPasswordRelogin); WhoAmI
  • Reads the host, realm and CA from /etc/ipa/default.conf and /etc/ipa/ca.crt on enrolled machines, or takes them explicitly (New with With* options)
  • Users: show, find, add (with random or given password), modify, enable, disable, delete
  • Passwords: set, change (with OTP), reset; typed errors for policy, invalid and expired passwords
  • SSH public keys and user authentication types (password, OTP, ...)
  • OTP tokens: add, list, enable, disable, remove, sync (SyncOTPToken)
  • Stage users: add, show, find, modify, activate, delete (StageUserAdd, StageUserActivate, ...)
  • Groups: show, find, add, modify, delete; members and member managers (GroupAddMember, GroupAddMemberManager, ...), with per-member failures returned as *MemberError
  • Hosts: show, find (HostShow, HostFind)
  • Host groups, services and keytab access, HBAC and sudo rules, certificates, DNS, automember rules, roles, privileges and permissions: see Typed objects
  • Lockout: per-replica failed logins and unlock (UserStatus, UserUnlock)
  • Password policy: group, global and effective per user (PwPolicyShow, UserPwPolicy)
  • Sub-IDs: find, generate (SubIDFind, SubIDGenerate)
  • HBAC and sudo: rule lookups and access checks (HBACRuleFind, SudoRuleFind, HBACTest)
  • Passkeys: add, remove (UserAddPasskey, UserRemovePasskey)
  • Typed errors: errors.Is(err, ipa.ErrNotFound) and friends; server errors are a bare *IpaError with Code, Name and Data
  • A …Context variant of every call that talks to the server (the Kerberos logins excepted)
  • RPC / RPCContext for any other command, reusing the client's TLS config, session or Kerberos auth and API version
  • Call[T] and Entry: typed decoding of any command's result, with accessors for FreeIPA's attribute lists, dates and binary values
  • FindEntries returns ErrTruncated when the server cut a search short; the typed Finds do so only with WithTruncationErrors()
  • Modify changes single attributes (setattr/addattr/delattr) on any object; Batch sends several commands in one round trip
  • ServerVersion; passkey and sub-ID calls return ErrNotSupported when the server is known to be older than FreeIPA 4.11 and 4.9.7
  • ipatest, a fake FreeIPA server for your own tests

See the roadmap for what is next.

Command catalogue and validation

Commands(version) and LookupCommand(name, version) list every FreeIPA command from 4.9.0 up to the newest catalogued release (4.13.4): positional arguments, options with their types, and the release that introduced each. An empty version means everything. The data is generated from FreeIPA's API.txt; go generate ./... refreshes it, and a nightly CI job fails when a new release adds something the catalogue lacks.

c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"), ipa.WithValidation())
// ...
_, err = c.RPC("user_show", []string{"jesse"}, ipa.Options{"no_such_option": true})
errors.Is(err, ipa.ErrInvalidCall) // true, nothing was sent

WithValidation is off by default. It rejects unknown commands, too many positional arguments and unknown options (ErrInvalidCall), and commands or options newer than the server (ErrNotSupported), for typed methods, RPC, Call, FindEntries and every call inside Batch. It does not check values or required options, and it is skipped when the server is newer than the catalogue. Validation is opt-in through New only (the old constructors never validate), and an option key that names a positional argument is accepted. The server version comes from the replica that answered last, so in a mixed 4.9/4.13 fleet behind a load balancer a call valid on 4.13 can get ErrNotSupported; Since values are upstream releases, so distro backports are not known.

For its built-in commands ipatest rejects options the command lacks at the SetVersion release (3005 OptionError, Unknown option: <name>) and commands added after that release (905). It does not count arguments or return ErrNotSupported, and Handle overrides are not checked.

Typed objects

Each object has typed …Show/…Find calls (and …Add, …Delete and member calls where noted), checked nightly against FreeIPA 4.9, 4.12 and 4.13. Member calls return the updated object and a *MemberError for members the server refused. Attributes are changed with Modify (HostGroupAdd and friends only create); for automember use RPC, since automember_mod needs the rule type. Finds that hit the server's size limit return what they got without an error; create the client with WithTruncationErrors() to get ErrTruncated with those entries instead.

Object Methods FreeIPA commands
Host HostAdd, HostAddWithPassword, HostMod, HostDelete, HostDisable (with HostShow/HostFind) host_add, _mod, _del (updatedns), _disable, _show, _find
Stage user StageUserAdd, StageUserAddWithPassword, StageUserActivate (with StageUserShow/StageUserFind) stageuser_add (with userpassword), _activate, _show, _find
Host group HostGroupShow, HostGroupFind, HostGroupAdd, HostGroupDelete, HostGroupAddMember, HostGroupRemoveMember, HostGroupAddMemberManager, HostGroupRemoveMemberManager hostgroup_show, _find, _add, _del, _add_member, _remove_member, _add_member_manager, _remove_member_manager
Service ServiceShow, ServiceFind, ServiceAdd, ServiceDelete, ServiceDisable, ServiceAddHost, ServiceRemoveHost, ServiceAllow…Keytab, ServiceDisallow…Keytab (retrieve, create) service_show, _find, _add, _del, _disable, _add_host, _remove_host, _allow_retrieve_keytab, _disallow_retrieve_keytab, _allow_create_keytab, _disallow_create_keytab
HBAC rule HBACRuleShow, HBACRuleFind, HBACRuleAdd, HBACRuleDelete, HBACRuleEnable, HBACRuleDisable, HBACRuleAdd/RemoveUser, …Host, …Service hbacrule_show, _find, _add, _del, _enable, _disable, _add_user, _remove_user, _add_host, _remove_host, _add_service, _remove_service
Sudo rule SudoRuleShow, SudoRuleFind, SudoRuleAdd, SudoRuleDelete, SudoRuleEnable, SudoRuleDisable, SudoRuleAdd/RemoveUser, …Host, …AllowCommand, …DenyCommand, …RunAsUser, …RunAsGroup, …Option sudorule_show, _find, _add, _del, _enable, _disable, _add_user, _add_host, _add_allow_command, _add_deny_command, _add_runasuser, _add_runasgroup, _add_option and their _remove_ twins
Certificate CertRequest, CertShow, CertRevoke cert_request, cert_show, cert_revoke
DNS zone DNSZoneShow, DNSZoneFind, DNSZoneAdd, DNSZoneDelete, DNSZoneEnable, DNSZoneDisable dnszone_show, _find, _add, _del, _enable, _disable
DNS record DNSRecordShow, DNSRecordFind, DNSRecordAdd, DNSRecordRemove, DNSRecordDelete dnsrecord_show, _find, _add, _del (remove values; del_all for the name)
Automember rule AutomemberShow, AutomemberFind, AutomemberAdd, AutomemberDelete, AutomemberAddCondition, AutomemberRemoveCondition, AutomemberDefaultGroup, AutomemberSetDefaultGroup, AutomemberRemoveDefaultGroup, AutomemberRebuild automember_show, _find, _add, _del, _add_condition, _remove_condition, automember_default_group_show, _set, _remove, automember_rebuild
Role, privilege, permission (read only) RoleShow/RoleFind, PrivilegeShow/PrivilegeFind, PermissionShow/PermissionFind role_*, privilege_*, permission_* _show and _find

Stability

goipa follows Semantic Versioning. From v1.0.0:

  • API. No exported identifier of ipa or ipatest is removed or changes signature within v1. This covers every identifier inherited from ubccr/goipa v0.0.7. Identifiers that newer ones supersede are marked Deprecated and stay. A breaking change would ship as github.com/neverlless/goipa/v2.
  • Errors. FreeIPA errors stay bare *IpaError values, and sentinels and error types stay matchable with errors.Is and errors.As as documented under Errors. Error message text is not part of the API.
  • Wire behaviour. A call sends the same command, arguments and options for the whole of v1, unless that shape is a bug against FreeIPA. Bugs are fixed in patch releases and listed in the ChangeLog.
  • FreeIPA. Supported: FreeIPA 4.9 (RHEL 8) to the latest 4.13 release, checked nightly against 4.9.13, 4.12.2 and 4.13.4; 4.10 and 4.11 are not tested. A newer FreeIPA release is added in a minor release. Dropping a FreeIPA line takes a minor release and a ChangeLog note one release ahead. Calls for features newer than the server fail with ErrNotSupported instead of reaching it.
  • Go. goipa supports the two most recent Go releases, as the Go team does. Go 1.26 (the go.mod minimum) and the newest stable release are tested in CI. The go directive in go.mod moves only in a minor release, never in a patch.
  • ipatest. Its API is stable as above. Its behaviour follows real FreeIPA and may change in minor releases (see the package documentation).
  • Command catalogue. Commands/LookupCommand data grows with new FreeIPA releases. The maintainer does not remove entries, except the few listed in allowedRemovals in internal/gencatalogue.

Security note: on FreeIPA (seen on 4.9.13, 4.12.2 and 4.13.4) the server keeps accepting a session cookie after session_logout, so logging out only makes the client forget it. Treat a session ID as a credential until it expires.

Install

go get github.com/neverlless/goipa

Requires Go 1.26 or newer. The package name is ipa.

Usage

On a host enrolled in FreeIPA (with /etc/ipa/default.conf), log in with a keytab and show a user:

package main

import (
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	client, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoginWithKeytab("/etc/myapp/myapp.keytab", "myapp"); err != nil {
		log.Fatal(err)
	}

	user, err := client.UserShow("jdoe")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%s <%s> uid=%s groups=%v\n", user.DisplayName, user.Email, user.Uid, user.Groups)
}

NewDefaultClient, NewClient and NewClientCustomHttp still work but are deprecated in favour of New.

Elsewhere, name the server and realm and log in with a password:

client, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"))
if err != nil {
	log.Fatal(err)
}
if err := client.RemoteLogin("jdoe", password); err != nil {
	switch {
	case errors.Is(err, ipa.ErrExpiredPassword):
		// ask for a new password, then client.SetPassword(...)
	case errors.Is(err, ipa.ErrInvalidPassword):
		// wrong password
	}
}
// Keep client.SessionID() and restore it later: ipa.New(...) then SetSessionID.

Which login to use

Method How it authenticates Needs Use when
RemoteLogin password over HTTPS (/ipa/session/login_password) the CA; no Kerberos web apps, scripts, hosts not enrolled
Login password through the KDC (Kerberos) krb5.conf (WithKrb5Config*), realm you have a password and want a ticket
LoginWithKeytab / LoginWithKeytabData keytab krb5.conf, realm services, daemons
LoginFromCCache / LoginFromCCacheData an existing ticket cache (kinit) krb5.conf CLI tools run by a logged-in user
saved session (SetSessionID) the ipa_session cookie none restoring a web session

Login is Kerberos, not the web login: it needs a KDC and a krb5.conf. To log in with a password over HTTPS, use RemoteLogin.

When a session expires (HTTP 401), the call is retried once:

  • Kerberos clients (Login, LoginWithKeytab*, LoginFromCCache*) clear the session and retry through SPNEGO. If another goroutine has already got a fresh session, it is reused.
  • RemoteLogin clients get ErrUnauthorized and the session is cleared, unless the client was created with WithPasswordRelogin. Then goipa logs in again with the password it kept in process memory and retries; goroutines that hit the 401 together share one login. A password FreeIPA rejects is forgotten, so it is not tried again, and ClearSession forgets it too. This needs sticky sessions (the default).
  • A client restored from a saved session ID has neither, so it gets ErrUnauthorized.

Kerberos clients send the first call to /ipa/json with SPNEGO; FreeIPA answers with an ipa_session cookie and later calls use /ipa/session/json with it, negotiating again only after a 401. The KDC therefore sees one ticket request per session, not one per call; after StickySession(false) every call negotiates SPNEGO. LoginFromCCache takes the path of a file cache, so strip a FILE: prefix taken from KRB5CCNAME. KCM caches are not read: RHEL and Fedora default to KCM:, so run kinit -c /tmp/krb5cc_app or use a keytab.

For a host that is not enrolled in FreeIPA, give the host, realm and CA:

client, err := ipa.New(
	ipa.WithHost("ipa.example.com"),
	ipa.WithRealm("EXAMPLE.COM"),
	ipa.WithCACert(caPEM), // the contents of /etc/ipa/ca.crt
)

Add WithKrb5Config(path) or WithKrb5ConfigData(text) for Kerberos logins, and WithPasswordRelogin() for the re-login above. With no options New reads /etc/ipa/default.conf and /etc/ipa/ca.crt, but only when a client is first created, not at import.

Full API reference: pkg.go.dev/github.com/neverlless/goipa.

Migrating from ubccr/goipa

The API is the same as ubccr/goipa v0.0.7. Change the import path:

grep -rl ubccr/goipa --include='*.go' . | xargs sed -i 's#ubccr/goipa#neverlless/goipa#'
go mod tidy

On macOS use sed -i ''. What changed since v0.0.7 is listed in the ChangeLog.

Differences from upstream

  • Security updates: golang.org/x/crypto and friends are current, and Dependabot and govulncheck keep them that way
  • Bug fixes: ErrUserExists no longer has the same message as ErrUnauthorized; Kerberos and request-building errors are returned instead of being ignored
  • go test ./... runs without a FreeIPA server; tests that need one are behind the integration build tag
  • CI with race detector, staticcheck, gosec and govulncheck
  • No logging: upstream's trace logs wrote passwords, random passwords and session cookies into the caller's log
  • A Client is safe for concurrent use
  • include and includedir in krb5.conf are resolved, so Kerberos logins work on ipa-client 4.13 hosts
  • The RPC escape hatch, typed errors and context.Context support
  • ipatest, a fake FreeIPA server, and contract tests that run the same checks nightly against real FreeIPA 4.9, 4.12 and 4.13

Credits

goipa builds on ubccr/goipa by Andrew E. Bruno, and on work from its pull requests and forks: @earthquakesan, @ivanovilia96, @m-vinc, @farzandalaee, @Demacr (UsersFindBy, now UserFind), @tubby1981, @fajo-de and @sitnikovv. Thank you. If you maintain a fork with changes that are not here, you are welcome to send them: open an issue or a pull request (see CONTRIBUTING.md).

Development

go test -race ./...

Consumers can test their own code without a FreeIPA server using the fake in ipatest.

Integration tests run against a real FreeIPA in a container (Linux, Docker, sudo):

scripts/ipa-up.sh && (set -a; . ./.env; set +a; go test -race -tags integration -count=1 ./...) ; scripts/ipa-up.sh down

ipa-up.sh rewrites /etc/krb5.conf (backed up once to /etc/krb5.conf.goipa-bak), /etc/ipa/ and your ccache, and refuses to run on a host whose /etc/ipa/default.conf points at another IPA server unless FORCE=1 is set.

Recorded responses

ipatest models the commands above and answers any other *_show or *_find command from responses recorded on real FreeIPA 4.9.13, 4.12.2 and 4.13.4 (secrets redacted), so tests of commands goipa does not wrap see real shapes. Order: a Handle override, then a built-in, then a recording, then 905. Server.SetReplay(nil) turns recordings off and SetReplay(fsys) uses your own, written by ipatest.NewRecorder. The recordings are about 3 MB, embedded in ipatest only.

See CONTRIBUTING.md before sending a pull request.

Security

Report vulnerabilities privately; see SECURITY.md.

License

goipa is released under a BSD-style license. See LICENSE and NOTICE. Copyright 2015 Andrew E. Bruno and the goipa authors (AUTHORS.rst).

Documentation

Overview

Package ipa is a Go client for the FreeIPA JSON-RPC API. It is a maintained continuation of github.com/ubccr/goipa.

Create a Client with New and its With* options; on a host enrolled in FreeIPA, New() alone reads /etc/ipa. A *Client is safe for concurrent use.

Calls from ubccr/goipa keep their names; calls added since are named Object+Verb (GroupAdd, HostGroupShow). Add calls take a struct where FreeIPA takes many attributes, positional values where it takes a key and a flag.

Which login to use

RemoteLogin                                password over HTTPS (/ipa/session/login_password).
                                           Needs the CA, no Kerberos. Web apps, scripts, hosts not enrolled.
Login                                      password through the KDC (Kerberos). Needs krb5.conf
                                           (DefaultKerbConf, or WithKrb5Config*) and a realm.
LoginWithKeytab, LoginWithKeytabData       keytab; needs krb5.conf (DefaultKerbConf, or WithKrb5Config*)
                                           and a realm. Services, daemons.
LoginFromCCache, LoginFromCCacheData       an existing ticket cache (kinit); needs krb5.conf
                                           (DefaultKerbConf, or WithKrb5Config*). CLI tools.
SetSessionID                               an ipa_session cookie. Restoring a web session.

Login is Kerberos, not the web login; use RemoteLogin for a password over HTTPS. For a host not enrolled in FreeIPA:

c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"), ipa.WithCACert(pem))

When a session expires (HTTP 401) the call is retried once; a fresh session another goroutine already obtained is reused. Kerberos clients clear the session and retry through SPNEGO. A RemoteLogin client created with WithPasswordRelogin logs in again with the password it keeps in memory, one login for all goroutines that hit the 401 (a password FreeIPA rejects is forgotten; this needs sticky sessions, the default). Any other client gets ErrUnauthorized and its session is cleared. The retry relies on FreeIPA's httpd answering 401 before it runs the command; a proxy that answers 401 after forwarding the request breaks that.

Any command

RPC calls any command goipa does not wrap and returns the raw response. Call decodes the result of any command into a type of your choice; Entry reads FreeIPA's attribute encoding (lists, dates, binary values):

u, _, err := ipa.Call[ipa.Entry](ctx, c, "user_show", []string{"jesse"}, ipa.Options{"all": true})
fmt.Println(u.Str("uid"), u.Strs("mail"), u.Time("krbpasswordexpiration"))

FindEntries returns ErrTruncated with the entries it got when the server cut a search short; Modify changes single attributes; Batch sends several commands in one round trip.

Typed objects

Host groups, services (with keytab access), HBAC and sudo rules, certificates, DNS zones and records, automember rules, and roles, privileges and permissions (read only) have typed calls such as HostGroupShow and SudoRuleAddOption. Member calls return the updated object and a *MemberError for members the server refused; attribute changes go through Modify.

Command catalogue

Commands and LookupCommand describe every FreeIPA command from 4.9.0 on: positional arguments, options, and the release that introduced each. The data is generated from FreeIPA's API.txt (go generate). New(..., WithValidation()) checks each call against it before sending and returns ErrInvalidCall (or ErrNotSupported for a feature newer than the server). It is off by default, does not check values or required options, and does nothing when the server is newer than the newest catalogued release.

Sessions

On FreeIPA (seen on 4.9.13, 4.12.2 and 4.13.4) the server keeps accepting an ipa_session cookie after session_logout: logout only makes the client forget it. Treat a session ID as a credential until it expires, and do not log or share it. ClearSession drops the ID on the client side only.

A Kerberos client sends its first request to /ipa/json with SPNEGO; FreeIPA answers with an ipa_session cookie and later calls use /ipa/session/json with that cookie, so the KDC sees one ticket request per session. After StickySession(false) every call negotiates SPNEGO. LoginFromCCache takes the path of a file cache; strip a FILE: prefix taken from KRB5CCNAME.

Errors

A FreeIPA error is returned as a bare *IpaError, never wrapped. This applies to typed calls, RPC, Call, FindEntries, Modification.Run and each BatchResult.Err. Match it with errors.Is against ErrNotFound, ErrDuplicateEntry, ErrACI or ErrEmptyModlist (compared by code only), or read Code and Data through errors.As or err.(*ipa.IpaError). The Code* constants name the other codes.

Member calls (...AddMember, HBACRuleAddUser, ServiceAllow..., AutomemberAddCondition, ...) return the updated object together with a *MemberError listing what FreeIPA refused. In that case the call itself succeeded.

A response with a status other than 200 is a *HTTPError, and a 401 also matches ErrUnauthorized. The password form endpoints return ErrInvalidPassword, ErrExpiredPassword, ErrPasswordPolicy, ErrInvalidCredentials or ErrUnauthorized for the outcomes FreeIPA names.

Some errors come before anything is sent:

  • ErrNotSupported: the last server seen is too old for the call.
  • ErrInvalidCall: WithValidation rejected the call.

A Find returns ErrTruncated together with the entries it got, when the server cut the search short. This applies to the Finds added in v0.9 and to FindEntries. UserFind, GroupFind, HostFind, StageUserFind, SubIDFind, FetchOTPTokens, HBACRuleFind and SudoRuleFind did not report it in v1.0 and still do not, unless the Client was built WithTruncationErrors.

UserAdd keeps upstream's ErrUserExists for 4002.

Transport, TLS, context and Kerberos errors are returned as they come, or wrapped with %w and an "ipa:" prefix. Use errors.Is(err, context.DeadlineExceeded). Sentinels are matched with errors.Is, never ==. goipa does not log.

Context

Every Client method that talks to the server has a twin with a Context suffix that takes ctx first. The form without a suffix is exactly context.Background().

The context bounds the whole call:

  • the HTTP request,
  • the one retry after a 401,
  • a password re-login,
  • the per-option requests of SudoRuleAddOption.

Cancelling it also stops a call before anything is sent.

APIs added since v0.7 take a context only (Call, FindEntries, Batch, Modification.Run). New API in v1 follows that rule: a context-only generic or builder, or a method pair.

The Kerberos logins (Login, LoginWithKeytab, LoginFromCCache and their Data forms) take no context, because gokrb5 cannot be cancelled. SPNEGO header generation inside a Context call is not cancellable either.

goipa stores no context, and the Client's http.Client timeout (1 minute by default, or yours via WithHTTPClient) still applies.

Example (Login)

The Kerberos logins need a KDC, so this example is compiled but not run.

package main

import (
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"))
	if err != nil {
		log.Fatal(err)
	}
	if err := c.LoginWithKeytab("/etc/app/app.keytab", "svc-app"); err != nil {
		log.Fatal(err)
	}

	u, err := c.UserShow("jesse")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Username, u.Email)
}

Index

Examples

Constants

View Source
const (
	AutomemberGroup     = "group"
	AutomemberHostGroup = "hostgroup"
)

Automember rule types: a rule adds users to a group or hosts to a host group.

View Source
const (
	CodeVersion              = 901
	CodeCommand              = 905
	CodeReferer              = 911
	CodeACI                  = 2100
	CodeOption               = 3005
	CodeRequirement          = 3007
	CodeConversion           = 3008
	CodeValidation           = 3009
	CodeNotFound             = 4001
	CodeDuplicateEntry       = 4002
	CodeAlreadyActive        = 4009
	CodeAlreadyInactive      = 4010
	CodeNotGroupMember       = 4012
	CodeAlreadyGroupMember   = 4014
	CodeAttrValueNotFound    = 4026
	CodeAlreadyContainsValue = 4038
	CodeEmptyModlist         = 4202
	CodeDatabase             = 4203
	CodeObjectclassViolation = 4205
	CodeOnlyOneValueAllowed  = 4207
)

FreeIPA error codes (ipalib.errors).

View Source
const (
	DefaultKerbConf = "/etc/krb5.conf"
	// IpaClientVersion is the API version goipa sends by default; fixed for v1
	// so behaviour does not change with an upgrade. Override it per call with
	// the version option.
	IpaClientVersion  = "2.237"
	IpaDatetimeFormat = "20060102150405Z"
)
View Source
const (
	AlgorithmSHA1   = "sha1"
	AlgorithmSHA256 = "sha256"
	AlgorithmSHA384 = "sha384"
	AlgorithmSHA512 = "sha512"
)

OTP Token hash Algorithms supported by FreeIPA

View Source
const (
	TokenTypeTOTP = "totp"
	TokenTypeHOTP = "hotp"
)

OTP Token types supported by FreeIPA

Variables

View Source
var (
	ErrNotFound       = &IpaError{Code: CodeNotFound, Name: "NotFound", Message: "not found"}
	ErrDuplicateEntry = &IpaError{Code: CodeDuplicateEntry, Name: "DuplicateEntry", Message: "entry already exists"}
	ErrACI            = &IpaError{Code: CodeACI, Name: "ACIError", Message: "insufficient access"}
	ErrEmptyModlist   = &IpaError{Code: CodeEmptyModlist, Name: "EmptyModlist", Message: "no modifications to be performed"}
)

Sentinels for common FreeIPA errors. They are matched with errors.Is by code only; any other code is available through errors.As and IpaError.Code. Do not modify.

View Source
var (
	// ErrPasswordPolicy is returned when a password does not conform to the password policy
	ErrPasswordPolicy = errors.New("password does not conform to policy")

	// ErrInvalidPassword is returned when a password is invalid
	ErrInvalidPassword = errors.New("invalid current password")

	// ErrInvalidCredentials is returned by SyncOTPToken when FreeIPA rejects
	// the user, password or codes (X-IPA-TokenSync-Result: invalid-credentials).
	ErrInvalidCredentials = errors.New("invalid user, password or OTP codes")

	// ErrExpiredPassword is returned when a password is expired
	ErrExpiredPassword = errors.New("password expired")

	// ErrUnauthorized is returned when user is not authorized
	ErrUnauthorized = errors.New("unauthorized")

	// ErrUserExists is returned when user account already exists. UserAdd
	// returns it for FreeIPA's DuplicateEntry (4002).
	ErrUserExists = errors.New("user exists")
)

Sentinels for the password form endpoints and UserAdd, matched with errors.Is. Do not modify.

View Source
var ErrInvalidCall = errors.New("ipa: call does not match the FreeIPA command catalogue")

ErrInvalidCall is returned, before anything is sent, by a client built with WithValidation for a call the command catalogue says cannot succeed. Test with errors.Is.

View Source
var ErrNotSupported = errors.New("ipa: not supported by this FreeIPA server")

ErrNotSupported is returned, before anything is sent, by commands that need a newer FreeIPA than the one the client last talked to. The gate uses the version of the server that answered last, so behind a load balancer during a rolling upgrade it follows whichever replica that was. Test with errors.Is.

View Source
var ErrTruncated = errors.New("ipa: search truncated; raise sizelimit or narrow the search")

ErrTruncated is returned by FindEntries with the entries found when the server cut the search short.

Functions

func ParseDateTime deprecated

func ParseDateTime(str string) time.Time

Parse a FreeIPA datetime. Datetimes in FreeIPA are returned using a class-hint system. Values are stored as an array with a single element indicating the type and value, for example, '[{"__datetime__": "YYYY-MM-DDTHH:MM:SSZ"]}'

Deprecated: use Entry.Time (through Call[Entry]), or time.Parse(IpaDatetimeFormat, s).

Types

type AutomemberCondition added in v0.9.0

type AutomemberCondition struct{ Key, Regex string }

AutomemberCondition is one regular expression on an entry attribute, stored by FreeIPA as "key=regex".

type AutomemberRule added in v0.9.0

type AutomemberRule struct {
	Name, Type, Description string // cn, the type the call used, description
	// automemberinclusiveregex, automemberexclusiveregex
	Inclusive, Exclusive []AutomemberCondition
}

AutomemberRule is a FreeIPA automember rule. Its name is the target group or host group. A description change goes through RPC with automember_mod: that command needs the type option, which Modify does not send.

type BatchCall added in v0.7.0

type BatchCall struct {
	Method  string
	Args    []string
	Options Options
}

BatchCall is one command of a Batch: what RPC would take.

type BatchResult added in v0.7.0

type BatchResult struct {
	Result *Result
	Err    error
}

BatchResult is the outcome of one BatchCall: Result on success, otherwise Err, always a bare *IpaError with FreeIPA's error_code, error_name, error and error_kw (as Data); errors.Is, errors.As and err.(*ipa.IpaError) work on it. Err is an error, not *IpaError, so Err != nil holds only on failure.

type Certificate added in v0.9.0

type Certificate struct {
	SerialNumber        string    // serial_number (decimal)
	Subject, Issuer     string    // subject, issuer
	NotBefore, NotAfter time.Time // valid_not_before, valid_not_after
	DER                 []byte    // certificate (base64)
	Revoked             bool      // revoked
	RevocationReason    int       // revocation_reason, RFC 5280 code; meaningful only when Revoked
}

Certificate is a certificate issued by the FreeIPA CA. Certificates have no attributes to modify; Modify does not apply.

type Client

type Client struct {
	// contains filtered or unexported fields
}

FreeIPA Client

Methods with a Context suffix bound the HTTP request with the given context. The generic and builder APIs (Call, FindEntries, Batch, Modification.Run) exist only in that form, by design. Kerberos login and SPNEGO header generation are not cancellable (gokrb5 has no context support), so Login, LoginWithKeytab, LoginFromCCache and their Data variants have no Context twins.

When FreeIPA answers 401 for an expired session, the Client drops that session and, if it can, sends the request again once: a Kerberos client gets a new session through SPNEGO, a RemoteLogin client logs in again only with WithPasswordRelogin. Other clients get an error matching ErrUnauthorized. The retry assumes FreeIPA's httpd answers 401 before running the command, which a proxy answering 401 after forwarding breaks.

func New added in v0.6.0

func New(opts ...Option) (*Client, error)

New builds a Client from options. Without WithHost and WithRealm it takes them from /etc/ipa/default.conf; without WithCACert or WithHTTPClient it trusts /etc/ipa/ca.crt (else the system roots); without a Kerberos option it reads DefaultKerbConf. /etc/ipa is read only when an option is missing.

It fails when no host is known, when WithCACert holds no certificate, when WithCACert and WithHTTPClient are both given, or when an option gets an empty value. The realm may stay empty; only Kerberos login needs it.

Example

New names the server and CA explicitly, for a host not enrolled in FreeIPA; compiled but not run.

package main

import (
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	var caPEM []byte // the contents of the FreeIPA CA certificate

	c, err := ipa.New(
		ipa.WithHost("ipa.example.com"),
		ipa.WithRealm("EXAMPLE.COM"),
		ipa.WithCACert(caPEM),
	)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.RemoteLogin("jesse", "secret"); err != nil {
		log.Fatal(err)
	}
}

func NewClient deprecated

func NewClient(host, realm string) *Client

New IPA Client with host and realm

Deprecated: use New(WithHost(host)); add WithRealm(realm) for Kerberos logins.

func NewClientCustomHttp deprecated

func NewClientCustomHttp(host, realm string, httpClient *http.Client) *Client

New IPA Client with host, realm and custom http client

Deprecated: use New(WithHost(host), WithHTTPClient(httpClient)); add WithRealm(realm) for Kerberos logins.

func NewDefaultClient deprecated

func NewDefaultClient() *Client

New default IPA Client using host and realm from /etc/ipa/default.conf, read on first use

Deprecated: use New, which reads the same files and returns an error when there is no host.

func NewDefaultClientWithSession deprecated

func NewDefaultClientWithSession(sessionID string) *Client

New default IPA Client with existing sessionID using host and realm from /etc/ipa/default.conf, read on first use

Deprecated: use New, then SetSessionID.

func (*Client) AddOTPToken

func (c *Client) AddOTPToken(token *OTPToken) (*OTPToken, error)

Add OTP token. Returns new OTPToken

func (*Client) AddOTPTokenContext added in v0.2.0

func (c *Client) AddOTPTokenContext(ctx context.Context, token *OTPToken) (*OTPToken, error)

AddOTPTokenContext is like AddOTPToken but bounds the request with ctx.

func (*Client) AutomemberAdd added in v0.9.0

func (c *Client) AutomemberAdd(typ, name, description string) (*AutomemberRule, error)

AutomemberAdd creates a rule with `automember_add`. name is the target group or host group, which must exist. FreeIPA ships no privilege for changing automember rules, so this and the other rule changes need an admin.

func (*Client) AutomemberAddCondition added in v0.9.0

func (c *Client) AutomemberAddCondition(typ, name, key string, inclusive, exclusive []string) (*AutomemberRule, error)

AutomemberAddCondition adds inclusive and exclusive regular expressions on attribute key to a rule with `automember_add_condition` and returns the rule; it needs an admin. Conditions the rule already has are skipped silently.

func (*Client) AutomemberAddConditionContext added in v0.9.0

func (c *Client) AutomemberAddConditionContext(ctx context.Context, typ, name, key string, inclusive, exclusive []string) (*AutomemberRule, error)

AutomemberAddConditionContext is like AutomemberAddCondition but bounds the request with ctx.

func (*Client) AutomemberAddContext added in v0.9.0

func (c *Client) AutomemberAddContext(ctx context.Context, typ, name, description string) (*AutomemberRule, error)

AutomemberAddContext is like AutomemberAdd but bounds the request with ctx.

func (*Client) AutomemberDefaultGroup added in v0.9.0

func (c *Client) AutomemberDefaultGroup(typ string) (string, error)

AutomemberDefaultGroup returns the fallback group of type typ, which gets the entries no rule matches, with `automember_default_group_show`; "" when none is set. It requires the Automember Readers privilege (System: Read Automember Definitions).

func (*Client) AutomemberDefaultGroupContext added in v0.9.0

func (c *Client) AutomemberDefaultGroupContext(ctx context.Context, typ string) (string, error)

AutomemberDefaultGroupContext is like AutomemberDefaultGroup but bounds the request with ctx.

func (*Client) AutomemberDelete added in v0.9.0

func (c *Client) AutomemberDelete(typ string, names ...string) error

AutomemberDelete deletes rules with `automember_del`; it needs an admin. FreeIPA deletes the rules named before the first missing one and then fails.

func (*Client) AutomemberDeleteContext added in v0.9.0

func (c *Client) AutomemberDeleteContext(ctx context.Context, typ string, names ...string) error

AutomemberDeleteContext is like AutomemberDelete but bounds the request with ctx.

func (*Client) AutomemberFind added in v0.9.0

func (c *Client) AutomemberFind(typ string, options Options) ([]*AutomemberRule, error)

AutomemberFind lists the rules of type typ with `automember_find`; options are passed through (e.g. `description`). A truncated search returns the rules found and ErrTruncated. It requires the Automember Readers privilege (System: Read Automember Rules).

func (*Client) AutomemberFindContext added in v0.9.0

func (c *Client) AutomemberFindContext(ctx context.Context, typ string, options Options) ([]*AutomemberRule, error)

AutomemberFindContext is like AutomemberFind but bounds the request with ctx.

func (*Client) AutomemberRebuild added in v0.9.0

func (c *Client) AutomemberRebuild(typ string) error

AutomemberRebuild reapplies the rules of type typ to every existing user or host with `automember_rebuild` and waits for the task to finish. It requires the Automember Task Administrator privilege (Add Automember Rebuild Membership Task).

func (*Client) AutomemberRebuildContext added in v0.9.0

func (c *Client) AutomemberRebuildContext(ctx context.Context, typ string) error

AutomemberRebuildContext is like AutomemberRebuild but bounds the request with ctx.

func (*Client) AutomemberRemoveCondition added in v0.9.0

func (c *Client) AutomemberRemoveCondition(typ, name, key string, inclusive, exclusive []string) (*AutomemberRule, error)

AutomemberRemoveCondition removes conditions on attribute key from a rule with `automember_remove_condition` and returns the rule; it needs an admin. Conditions the rule lacks come back as *MemberError (Type the regex attribute, Name "key=regex") together with the rule.

func (*Client) AutomemberRemoveConditionContext added in v0.9.0

func (c *Client) AutomemberRemoveConditionContext(ctx context.Context, typ, name, key string, inclusive, exclusive []string) (*AutomemberRule, error)

AutomemberRemoveConditionContext is like AutomemberRemoveCondition but bounds the request with ctx.

func (*Client) AutomemberRemoveDefaultGroup added in v0.9.0

func (c *Client) AutomemberRemoveDefaultGroup(typ string) error

AutomemberRemoveDefaultGroup unsets the fallback group of type typ with `automember_default_group_remove`; with none set it fails with ErrNotFound. It needs an admin.

func (*Client) AutomemberRemoveDefaultGroupContext added in v0.9.0

func (c *Client) AutomemberRemoveDefaultGroupContext(ctx context.Context, typ string) error

AutomemberRemoveDefaultGroupContext is like AutomemberRemoveDefaultGroup but bounds the request with ctx.

func (*Client) AutomemberSetDefaultGroup added in v0.9.0

func (c *Client) AutomemberSetDefaultGroup(typ, group string) error

AutomemberSetDefaultGroup sets the fallback group of type typ with `automember_default_group_set`; setting the current one fails with ErrEmptyModlist. It needs an admin.

func (*Client) AutomemberSetDefaultGroupContext added in v0.9.0

func (c *Client) AutomemberSetDefaultGroupContext(ctx context.Context, typ, group string) error

AutomemberSetDefaultGroupContext is like AutomemberSetDefaultGroup but bounds the request with ctx.

func (*Client) AutomemberShow added in v0.9.0

func (c *Client) AutomemberShow(typ, name string) (*AutomemberRule, error)

AutomemberShow fetches a rule of type typ (AutomemberGroup or AutomemberHostGroup) with `automember_show`; it requires the Automember Readers privilege (System: Read Automember Rules).

func (*Client) AutomemberShowContext added in v0.9.0

func (c *Client) AutomemberShowContext(ctx context.Context, typ, name string) (*AutomemberRule, error)

AutomemberShowContext is like AutomemberShow but bounds the request with ctx.

func (*Client) Batch added in v0.7.0

func (c *Client) Batch(ctx context.Context, calls ...BatchCall) ([]BatchResult, error)

Batch runs calls in one FreeIPA batch request, in order, and returns one BatchResult per call. A failed command does not stop the others and does not make err non-nil; err is set only when the whole batch fails. The commands are not atomic: earlier ones stay applied when a later one fails. A result the client cannot decode fails the whole call, although the server ran the commands. No call's Options is modified.

Example

Batch runs several commands in one round trip; a failed command fills Err and does not fail the batch. Compiled but not run.

package main

import (
	"context"
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	res, err := c.Batch(context.Background(),
		ipa.BatchCall{Method: "user_show", Args: []string{"jesse"}},
		ipa.BatchCall{Method: "group_show", Args: []string{"admins"}},
	)
	if err != nil {
		log.Fatal(err)
	}
	for _, r := range res {
		if r.Err != nil {
			fmt.Println(r.Err)
		}
	}
}

func (*Client) CertRequest added in v0.9.0

func (c *Client) CertRequest(principal, csrPEM string) (*Certificate, error)

CertRequest submits a PEM certificate signing request for principal (e.g. host/<fqdn>) with `cert_request` under the default profile and returns the issued certificate. It requires the Certificate Administrators privilege (Request Certificate), or the right to request for that host or service itself.

func (*Client) CertRequestContext added in v0.9.0

func (c *Client) CertRequestContext(ctx context.Context, principal, csrPEM string) (*Certificate, error)

CertRequestContext is like CertRequest but bounds the request with ctx.

func (*Client) CertRevoke added in v0.9.0

func (c *Client) CertRevoke(serial string, reason int) error

CertRevoke revokes the certificate with decimal serial number serial with `cert_revoke`; reason is the RFC 5280 code (0 unspecified, 4 superseded, …). It requires the Certificate Administrators privilege (Revoke Certificate).

func (*Client) CertRevokeContext added in v0.9.0

func (c *Client) CertRevokeContext(ctx context.Context, serial string, reason int) error

CertRevokeContext is like CertRevoke but bounds the request with ctx.

func (*Client) CertShow added in v0.9.0

func (c *Client) CertShow(serial string) (*Certificate, error)

CertShow fetches the certificate with decimal serial number serial with `cert_show`. It requires the Certificate Administrators or Host Administrators privilege (Retrieve Certificates from the CA), or a host principal named in the certificate's subject CN; anyone else gets ErrACI.

func (*Client) CertShowContext added in v0.9.0

func (c *Client) CertShowContext(ctx context.Context, serial string) (*Certificate, error)

CertShowContext is like CertShow but bounds the request with ctx.

func (*Client) ChangePassword

func (c *Client) ChangePassword(username, oldPasswd, newPasswd, otpcode string) error

Change user password. This will run the passwd ipa command. Optionally provide an OTP if required

Unlike SetPassword, it needs a session (or Kerberos) to run passwd.

func (*Client) ChangePasswordContext added in v0.2.0

func (c *Client) ChangePasswordContext(ctx context.Context, username, oldPasswd, newPasswd, otpcode string) error

ChangePasswordContext is like ChangePassword but bounds the request with ctx.

func (*Client) ClearSession

func (c *Client) ClearSession()

Clears out FreeIPA session id and the credentials kept by WithPasswordRelogin, so the Client does not log back in on its own.

func (*Client) DNSRecordAdd added in v0.9.0

func (c *Client) DNSRecordAdd(zone, name, rtype string, values ...string) (*DNSRecord, error)

DNSRecordAdd adds values of type rtype (case-insensitive, "A" or "txt") at name in zone with `dnsrecord_add`, creating the name if needed, and returns all its records. A type the command catalogue does not know fails with ErrInvalidCall before anything is sent. It requires the DNS Administrators privilege (System: Add DNS Entries, or Update DNS Entries for an existing name).

func (*Client) DNSRecordAddContext added in v0.9.0

func (c *Client) DNSRecordAddContext(ctx context.Context, zone, name, rtype string, values ...string) (*DNSRecord, error)

DNSRecordAddContext is like DNSRecordAdd but bounds the request with ctx.

func (*Client) DNSRecordDelete added in v0.9.0

func (c *Client) DNSRecordDelete(zone, name string) error

DNSRecordDelete deletes name and all its records from zone with `dnsrecord_del` del_all; it requires the DNS Administrators privilege (System: Remove DNS Entries).

func (*Client) DNSRecordDeleteContext added in v0.9.0

func (c *Client) DNSRecordDeleteContext(ctx context.Context, zone, name string) error

DNSRecordDeleteContext is like DNSRecordDelete but bounds the request with ctx.

func (*Client) DNSRecordFind added in v0.9.0

func (c *Client) DNSRecordFind(zone string, options Options) ([]*DNSRecord, error)

DNSRecordFind finds the record names of zone with `dnsrecord_find`; options are passed through (e.g. `idnsname`, `arecord`, `sizelimit`). A truncated search returns the records found and ErrTruncated. It requires the DNS Administrators privilege (System: Read DNS Entries).

func (*Client) DNSRecordFindContext added in v0.9.0

func (c *Client) DNSRecordFindContext(ctx context.Context, zone string, options Options) ([]*DNSRecord, error)

DNSRecordFindContext is like DNSRecordFind but bounds the request with ctx.

func (*Client) DNSRecordRemove added in v0.9.0

func (c *Client) DNSRecordRemove(zone, name, rtype string, values ...string) error

DNSRecordRemove removes values of type rtype at name in zone with `dnsrecord_del`; FreeIPA deletes the name when no records are left. It requires the DNS Administrators privilege (System: Update DNS Entries).

Call DNSRecordShow for the records left.

func (*Client) DNSRecordRemoveContext added in v0.9.0

func (c *Client) DNSRecordRemoveContext(ctx context.Context, zone, name, rtype string, values ...string) error

DNSRecordRemoveContext is like DNSRecordRemove but bounds the request with ctx.

func (*Client) DNSRecordShow added in v0.9.0

func (c *Client) DNSRecordShow(zone, name string) (*DNSRecord, error)

DNSRecordShow fetches the records at name in zone with `dnsrecord_show`; it requires the DNS Administrators privilege (System: Read DNS Entries).

func (*Client) DNSRecordShowContext added in v0.9.0

func (c *Client) DNSRecordShowContext(ctx context.Context, zone, name string) (*DNSRecord, error)

DNSRecordShowContext is like DNSRecordShow but bounds the request with ctx.

func (*Client) DNSZoneAdd added in v0.9.0

func (c *Client) DNSZoneAdd(name string, force bool) (*DNSZone, error)

DNSZoneAdd creates a master zone with `dnszone_add` and returns it; force is FreeIPA's force flag, which skips the name server and overlap checks. It requires the DNS Administrators privilege (System: Add DNS Entries).

func (*Client) DNSZoneAddContext added in v0.9.0

func (c *Client) DNSZoneAddContext(ctx context.Context, name string, force bool) (*DNSZone, error)

DNSZoneAddContext is like DNSZoneAdd but bounds the request with ctx.

func (*Client) DNSZoneDelete added in v0.9.0

func (c *Client) DNSZoneDelete(names ...string) error

DNSZoneDelete deletes zones, with all their records, with `dnszone_del`; it requires the DNS Administrators privilege (System: Remove DNS Entries).

func (*Client) DNSZoneDeleteContext added in v0.9.0

func (c *Client) DNSZoneDeleteContext(ctx context.Context, names ...string) error

DNSZoneDeleteContext is like DNSZoneDelete but bounds the request with ctx.

func (*Client) DNSZoneDisable added in v0.9.0

func (c *Client) DNSZoneDisable(name string) error

DNSZoneDisable deactivates a zone with `dnszone_disable`; disabling a disabled zone succeeds. It requires the DNS Administrators privilege (System: Update DNS Entries).

func (*Client) DNSZoneDisableContext added in v0.9.0

func (c *Client) DNSZoneDisableContext(ctx context.Context, name string) error

DNSZoneDisableContext is like DNSZoneDisable but bounds the request with ctx.

func (*Client) DNSZoneEnable added in v0.9.0

func (c *Client) DNSZoneEnable(name string) error

DNSZoneEnable activates a zone with `dnszone_enable`; it requires the DNS Administrators privilege (System: Update DNS Entries).

func (*Client) DNSZoneEnableContext added in v0.9.0

func (c *Client) DNSZoneEnableContext(ctx context.Context, name string) error

DNSZoneEnableContext is like DNSZoneEnable but bounds the request with ctx.

func (*Client) DNSZoneFind added in v0.9.0

func (c *Client) DNSZoneFind(options Options) ([]*DNSZone, error)

DNSZoneFind finds zones with `dnszone_find`; options are passed through (e.g. `idnsname`, `sizelimit`). A truncated search returns the zones found and ErrTruncated. It requires the DNS Administrators privilege (System: Read DNS Entries).

func (*Client) DNSZoneFindContext added in v0.9.0

func (c *Client) DNSZoneFindContext(ctx context.Context, options Options) ([]*DNSZone, error)

DNSZoneFindContext is like DNSZoneFind but bounds the request with ctx.

func (*Client) DNSZoneShow added in v0.9.0

func (c *Client) DNSZoneShow(name string) (*DNSZone, error)

DNSZoneShow fetches a zone with `dnszone_show`; it requires the DNS Administrators privilege (System: Read DNS Entries).

func (*Client) DNSZoneShowContext added in v0.9.0

func (c *Client) DNSZoneShowContext(ctx context.Context, name string) (*DNSZone, error)

DNSZoneShowContext is like DNSZoneShow but bounds the request with ctx.

func (*Client) DisableOTPToken

func (c *Client) DisableOTPToken(tokenUUID string) error

Disable OTP token.

func (*Client) DisableOTPTokenContext added in v0.2.0

func (c *Client) DisableOTPTokenContext(ctx context.Context, tokenUUID string) error

DisableOTPTokenContext is like DisableOTPToken but bounds the request with ctx.

func (*Client) EnableOTPToken

func (c *Client) EnableOTPToken(tokenUUID string) error

Enable OTP token.

func (*Client) EnableOTPTokenContext added in v0.2.0

func (c *Client) EnableOTPTokenContext(ctx context.Context, tokenUUID string) error

EnableOTPTokenContext is like EnableOTPToken but bounds the request with ctx.

func (*Client) FetchOTPTokens

func (c *Client) FetchOTPTokens(owner string) ([]*OTPToken, error)

Fetch OTP tokens by owner.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) FetchOTPTokensContext added in v0.2.0

func (c *Client) FetchOTPTokensContext(ctx context.Context, owner string) ([]*OTPToken, error)

FetchOTPTokensContext is like FetchOTPTokens but bounds the request with ctx.

func (*Client) GroupAdd added in v0.4.0

func (c *Client) GroupAdd(group *Group) (*Group, error)

GroupAdd creates a group with `group_add` and returns it; it requires the Group Administrators privilege (System: Add Groups). A zero Group creates a POSIX group, as `ipa group-add` does; set NonPOSIX for a group without a GID.

func (*Client) GroupAddContext added in v0.4.0

func (c *Client) GroupAddContext(ctx context.Context, group *Group) (*Group, error)

GroupAddContext is like GroupAdd but bounds the request with ctx.

func (*Client) GroupAddMember added in v0.4.0

func (c *Client) GroupAddMember(group string, users, groups []string) (*Group, error)

GroupAddMember adds users and groups to a group with `group_add_member`. It needs the Group Administrators or Modify Group membership privilege, or the caller is a member manager of the group; per-member problems, including insufficient access, are returned as *MemberError, together with the group as it stands. This is the context-aware API from ubccr/goipa#17, generalised to users and groups.

func (*Client) GroupAddMemberContext added in v0.4.0

func (c *Client) GroupAddMemberContext(ctx context.Context, group string, users, groups []string) (*Group, error)

GroupAddMemberContext is like GroupAddMember but bounds the request with ctx.

func (*Client) GroupAddMemberManager added in v0.4.0

func (c *Client) GroupAddMemberManager(group string, users, groups []string) (*Group, error)

GroupAddMemberManager makes users and groups member managers of a group with `group_add_member_manager`; it requires the Group Administrators privilege (System: Modify Groups). Per-member problems are returned as *MemberError, together with the group as it stands.

func (*Client) GroupAddMemberManagerContext added in v0.4.0

func (c *Client) GroupAddMemberManagerContext(ctx context.Context, group string, users, groups []string) (*Group, error)

GroupAddMemberManagerContext is like GroupAddMemberManager but bounds the request with ctx.

func (*Client) GroupDelete added in v0.4.0

func (c *Client) GroupDelete(names ...string) error

GroupDelete deletes groups with `group_del`; it requires the Group Administrators privilege (System: Remove Groups).

func (*Client) GroupDeleteContext added in v0.4.0

func (c *Client) GroupDeleteContext(ctx context.Context, names ...string) error

GroupDeleteContext is like GroupDelete but bounds the request with ctx.

func (*Client) GroupFind added in v0.4.0

func (c *Client) GroupFind(options Options) ([]*Group, error)

GroupFind finds groups with `group_find`; options are passed through (e.g. `cn`, `user`, `in_group`, `sizelimit`). Any authenticated user may read groups (System: Read Groups).

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) GroupFindContext added in v0.4.0

func (c *Client) GroupFindContext(ctx context.Context, options Options) ([]*Group, error)

GroupFindContext is like GroupFind but bounds the request with ctx.

func (*Client) GroupMod added in v0.4.0

func (c *Client) GroupMod(group *Group) (*Group, error)

GroupMod changes a group's description (an empty one clears it) and, for a POSIX group, its GID with `group_mod`; it requires the Group Administrators privilege (System: Modify Groups). It returns group itself when nothing changed. Conversion between group types and renames go through RPC.

func (*Client) GroupModContext added in v0.4.0

func (c *Client) GroupModContext(ctx context.Context, group *Group) (*Group, error)

GroupModContext is like GroupMod but bounds the request with ctx.

func (*Client) GroupRemoveMember added in v0.4.0

func (c *Client) GroupRemoveMember(group string, users, groups []string) (*Group, error)

GroupRemoveMember removes users and groups from a group with `group_remove_member`. It needs the Group Administrators or Modify Group membership privilege, or the caller is a member manager of the group; per-member problems, including insufficient access, are returned as *MemberError, together with the group as it stands.

func (*Client) GroupRemoveMemberContext added in v0.4.0

func (c *Client) GroupRemoveMemberContext(ctx context.Context, group string, users, groups []string) (*Group, error)

GroupRemoveMemberContext is like GroupRemoveMember but bounds the request with ctx.

func (*Client) GroupRemoveMemberManager added in v0.4.0

func (c *Client) GroupRemoveMemberManager(group string, users, groups []string) (*Group, error)

GroupRemoveMemberManager removes member managers from a group with `group_remove_member_manager`; it requires the Group Administrators privilege (System: Modify Groups). Per-member problems are returned as *MemberError, together with the group as it stands.

func (*Client) GroupRemoveMemberManagerContext added in v0.4.0

func (c *Client) GroupRemoveMemberManagerContext(ctx context.Context, group string, users, groups []string) (*Group, error)

GroupRemoveMemberManagerContext is like GroupRemoveMemberManager but bounds the request with ctx.

func (*Client) GroupShow added in v0.4.0

func (c *Client) GroupShow(name string) (*Group, error)

GroupShow fetches a group with `group_show`. Any authenticated user may read groups (System: Read Groups).

func (*Client) GroupShowContext added in v0.4.0

func (c *Client) GroupShowContext(ctx context.Context, name string) (*Group, error)

GroupShowContext is like GroupShow but bounds the request with ctx.

func (*Client) HBACRuleAdd added in v0.9.0

func (c *Client) HBACRuleAdd(r *HBACRule) (*HBACRule, error)

HBACRuleAdd creates an HBAC rule with `hbacrule_add`; it requires the HBAC Administrator privilege (System: Add HBAC Rule). It sends the name, the description and the categories set to "all"; members are added with the HBACRuleAdd* calls. Enabled is ignored: new rules are enabled.

func (*Client) HBACRuleAddContext added in v0.9.0

func (c *Client) HBACRuleAddContext(ctx context.Context, r *HBACRule) (*HBACRule, error)

HBACRuleAddContext is like HBACRuleAdd but bounds the request with ctx.

func (*Client) HBACRuleAddHost added in v0.9.0

func (c *Client) HBACRuleAddHost(name string, hosts, hostgroups []string) (*HBACRule, error)

HBACRuleAddHost adds hosts and host groups to an HBAC rule with `hbacrule_add_host`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). A rule with host category "all" is 4303 MutuallyExclusiveError. Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleAddHostContext added in v0.9.0

func (c *Client) HBACRuleAddHostContext(ctx context.Context, name string, hosts, hostgroups []string) (*HBACRule, error)

HBACRuleAddHostContext is like HBACRuleAddHost but bounds the request with ctx.

func (*Client) HBACRuleAddService added in v0.9.0

func (c *Client) HBACRuleAddService(name string, services, servicegroups []string) (*HBACRule, error)

HBACRuleAddService adds HBAC services (hbacsvc) and service groups (hbacsvcgroup) to an HBAC rule with `hbacrule_add_service`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). A rule with service category "all" is 4303 MutuallyExclusiveError. Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleAddServiceContext added in v0.9.0

func (c *Client) HBACRuleAddServiceContext(ctx context.Context, name string, services, servicegroups []string) (*HBACRule, error)

HBACRuleAddServiceContext is like HBACRuleAddService but bounds the request with ctx.

func (*Client) HBACRuleAddUser added in v0.9.0

func (c *Client) HBACRuleAddUser(name string, users, groups []string) (*HBACRule, error)

HBACRuleAddUser adds users and groups to an HBAC rule with `hbacrule_add_user`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). A rule with user category "all" is 4303 MutuallyExclusiveError. Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleAddUserContext added in v0.9.0

func (c *Client) HBACRuleAddUserContext(ctx context.Context, name string, users, groups []string) (*HBACRule, error)

HBACRuleAddUserContext is like HBACRuleAddUser but bounds the request with ctx.

func (*Client) HBACRuleDelete added in v0.9.0

func (c *Client) HBACRuleDelete(names ...string) error

HBACRuleDelete deletes HBAC rules with `hbacrule_del` in one call; it requires the HBAC Administrator privilege (System: Delete HBAC Rule).

func (*Client) HBACRuleDeleteContext added in v0.9.0

func (c *Client) HBACRuleDeleteContext(ctx context.Context, names ...string) error

HBACRuleDeleteContext is like HBACRuleDelete but bounds the request with ctx.

func (*Client) HBACRuleDisable added in v0.9.0

func (c *Client) HBACRuleDisable(name string) error

HBACRuleDisable disables an HBAC rule with `hbacrule_disable`; it requires the HBAC Administrator privilege (System: Modify HBAC Rule). Disabling a disabled rule succeeds.

func (*Client) HBACRuleDisableContext added in v0.9.0

func (c *Client) HBACRuleDisableContext(ctx context.Context, name string) error

HBACRuleDisableContext is like HBACRuleDisable but bounds the request with ctx.

func (*Client) HBACRuleEnable added in v0.9.0

func (c *Client) HBACRuleEnable(name string) error

HBACRuleEnable enables an HBAC rule with `hbacrule_enable`; it requires the HBAC Administrator privilege (System: Modify HBAC Rule). Enabling an enabled rule succeeds.

func (*Client) HBACRuleEnableContext added in v0.9.0

func (c *Client) HBACRuleEnableContext(ctx context.Context, name string) error

HBACRuleEnableContext is like HBACRuleEnable but bounds the request with ctx.

func (*Client) HBACRuleFind added in v0.5.0

func (c *Client) HBACRuleFind(options Options) ([]*HBACRule, error)

HBACRuleFind finds HBAC rules with `hbacrule_find`; options are passed through (e.g. `cn`, `ipaenabledflag`, `sizelimit`). Any authenticated user may read rules (System: Read HBAC Rules). FreeIPA returns at most its search limit (100 by default) unless `sizelimit` is set.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) HBACRuleFindContext added in v0.5.0

func (c *Client) HBACRuleFindContext(ctx context.Context, options Options) ([]*HBACRule, error)

HBACRuleFindContext is like HBACRuleFind but bounds the request with ctx.

func (*Client) HBACRuleRemoveHost added in v0.9.0

func (c *Client) HBACRuleRemoveHost(name string, hosts, hostgroups []string) (*HBACRule, error)

HBACRuleRemoveHost removes hosts and host groups from an HBAC rule with `hbacrule_remove_host`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleRemoveHostContext added in v0.9.0

func (c *Client) HBACRuleRemoveHostContext(ctx context.Context, name string, hosts, hostgroups []string) (*HBACRule, error)

HBACRuleRemoveHostContext is like HBACRuleRemoveHost but bounds the request with ctx.

func (*Client) HBACRuleRemoveService added in v0.9.0

func (c *Client) HBACRuleRemoveService(name string, services, servicegroups []string) (*HBACRule, error)

HBACRuleRemoveService removes HBAC services and service groups from an HBAC rule with `hbacrule_remove_service`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleRemoveServiceContext added in v0.9.0

func (c *Client) HBACRuleRemoveServiceContext(ctx context.Context, name string, services, servicegroups []string) (*HBACRule, error)

HBACRuleRemoveServiceContext is like HBACRuleRemoveService but bounds the request with ctx.

func (*Client) HBACRuleRemoveUser added in v0.9.0

func (c *Client) HBACRuleRemoveUser(name string, users, groups []string) (*HBACRule, error)

HBACRuleRemoveUser removes users and groups from an HBAC rule with `hbacrule_remove_user`; it requires the HBAC Administrator privilege (System: Manage HBAC Rule Membership). Per-member problems are returned as *MemberError, together with the rule as it stands.

func (*Client) HBACRuleRemoveUserContext added in v0.9.0

func (c *Client) HBACRuleRemoveUserContext(ctx context.Context, name string, users, groups []string) (*HBACRule, error)

HBACRuleRemoveUserContext is like HBACRuleRemoveUser but bounds the request with ctx.

func (*Client) HBACRuleShow added in v0.9.0

func (c *Client) HBACRuleShow(name string) (*HBACRule, error)

HBACRuleShow fetches an HBAC rule with `hbacrule_show`. Any authenticated user may read rules (System: Read HBAC Rules). Attributes the typed calls do not cover change through Modify("hbacrule_mod", name).

func (*Client) HBACRuleShowContext added in v0.9.0

func (c *Client) HBACRuleShowContext(ctx context.Context, name string) (*HBACRule, error)

HBACRuleShowContext is like HBACRuleShow but bounds the request with ctx.

func (*Client) HBACTest added in v0.5.0

func (c *Client) HBACTest(user, host, service string, rules ...string) (*HBACTestResult, error)

HBACTest runs `hbactest`. It evaluates HBAC rules on the server: every enabled rule, or only rules, disabled ones included. Any authenticated user may run it; it reads rules and group membership as the caller. FreeIPA ignores an unknown user, host or service instead of failing, so a typo reads as denied. If a name in rules does not exist, nothing is evaluated: Granted is false and Errors lists the unresolved names.

func (*Client) HBACTestContext added in v0.5.0

func (c *Client) HBACTestContext(ctx context.Context, user, host, service string, rules ...string) (*HBACTestResult, error)

HBACTestContext is like HBACTest but bounds the request with ctx.

func (*Client) Host

func (c *Client) Host() string

Returns FreeIPA server hostname

func (*Client) HostAdd added in v1.1.0

func (c *Client) HostAdd(h *Host, force, random bool) (*Host, error)

HostAdd adds a host with `host_add`; it requires the Host Administrators privilege (System: Add Hosts). force skips FreeIPA's DNS check of the fqdn. If random is true the server generates a one-time enrollment password, returned in RandomPassword. Adding an existing host returns the bare *IpaError (ErrDuplicateEntry).

Example
package main

import (
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
	"github.com/neverlless/goipa/ipatest"
)

func main() {
	s := ipatest.New()
	defer s.Close()
	c := s.ClientAs("admin")

	h, err := c.HostAdd(&ipa.Host{FQDN: "web1.example.com"}, true, true)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(h.FQDN, h.RandomPassword != "")

	if err := c.HostDelete(false, h.FQDN); err != nil {
		log.Fatal(err)
	}
}
Output:
web1.example.com true

func (*Client) HostAddContext added in v1.1.0

func (c *Client) HostAddContext(ctx context.Context, h *Host, force, random bool) (*Host, error)

HostAddContext is like HostAdd but bounds the request with ctx.

func (*Client) HostAddWithPassword added in v1.1.0

func (c *Client) HostAddWithPassword(h *Host, force bool, password string) (*Host, error)

HostAddWithPassword adds a host with a one-time enrollment password (`host_add` with userpassword); it requires the Host Administrators privilege (System: Add Hosts). Adding an existing host returns the bare *IpaError (ErrDuplicateEntry).

func (*Client) HostAddWithPasswordContext added in v1.1.0

func (c *Client) HostAddWithPasswordContext(ctx context.Context, h *Host, force bool, password string) (*Host, error)

HostAddWithPasswordContext is like HostAddWithPassword but bounds the request with ctx.

func (*Client) HostDelete added in v1.1.0

func (c *Client) HostDelete(updateDNS bool, fqdns ...string) error

HostDelete deletes hosts with `host_del`; it requires the Host Administrators privilege (System: Remove Hosts). If updateDNS is true the host's DNS records are removed too.

func (*Client) HostDeleteContext added in v1.1.0

func (c *Client) HostDeleteContext(ctx context.Context, updateDNS bool, fqdns ...string) error

HostDeleteContext is like HostDelete but bounds the request with ctx.

func (*Client) HostDisable added in v1.1.0

func (c *Client) HostDisable(fqdn string) error

HostDisable disables a host with `host_disable`: it removes the Kerberos keys of the host and of its services and, with the CA on, revokes and removes its certificates. The one-time password stays. It requires the Host Administrators privilege (System: Manage Host Keytab). If there is nothing to remove, which includes a host that was only added and never enrolled, it returns the bare *IpaError 4010 (AlreadyInactive).

func (*Client) HostDisableContext added in v1.1.0

func (c *Client) HostDisableContext(ctx context.Context, fqdn string) error

HostDisableContext is like HostDisable but bounds the request with ctx.

func (*Client) HostFind added in v0.4.0

func (c *Client) HostFind(options Options) ([]*Host, error)

HostFind finds hosts with `host_find`; options are passed through (e.g. `fqdn`, `in_hostgroup`, `sizelimit`). Any authenticated user may read hosts (System: Read Hosts). ubccr/goipa#11.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) HostFindContext added in v0.4.0

func (c *Client) HostFindContext(ctx context.Context, options Options) ([]*Host, error)

HostFindContext is like HostFind but bounds the request with ctx.

func (*Client) HostGroupAdd added in v0.9.0

func (c *Client) HostGroupAdd(g *HostGroup) (*HostGroup, error)

HostGroupAdd creates a host group with `hostgroup_add` from g's Name and Description and returns it; it requires the Host Group Administrators privilege (System: Add Hostgroups).

func (*Client) HostGroupAddContext added in v0.9.0

func (c *Client) HostGroupAddContext(ctx context.Context, g *HostGroup) (*HostGroup, error)

HostGroupAddContext is like HostGroupAdd but bounds the request with ctx.

func (*Client) HostGroupAddMember added in v0.9.0

func (c *Client) HostGroupAddMember(name string, hosts, hostgroups []string) (*HostGroup, error)

HostGroupAddMember adds hosts and host groups to a host group with `hostgroup_add_member`. It needs the Host Group Administrators privilege (System: Modify Hostgroup Membership), or the caller is a member manager of the group; per-member problems are returned as *MemberError, together with the group as it stands.

Example

Member calls return the updated group and a *MemberError for members the server refused. The example is compiled but not run.

package main

import (
	"errors"
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"))
	if err != nil {
		log.Fatal(err)
	}
	g, err := c.HostGroupAddMember("web", []string{"web1.example.com", "typo.example.com"}, nil)

	var me *ipa.MemberError
	if errors.As(err, &me) {
		for _, f := range me.Failures {
			fmt.Println("not added:", f.Name, f.Message)
		}
	} else if err != nil {
		log.Fatal(err)
	}
	fmt.Println(g.Name, g.Hosts)
}

func (*Client) HostGroupAddMemberContext added in v0.9.0

func (c *Client) HostGroupAddMemberContext(ctx context.Context, name string, hosts, hostgroups []string) (*HostGroup, error)

HostGroupAddMemberContext is like HostGroupAddMember but bounds the request with ctx.

func (*Client) HostGroupAddMemberManager added in v0.9.0

func (c *Client) HostGroupAddMemberManager(name string, users, groups []string) (*HostGroup, error)

HostGroupAddMemberManager makes users and groups member managers of a host group with `hostgroup_add_member_manager`; it requires the Host Group Administrators privilege (System: Modify Hostgroups). Per-member problems are returned as *MemberError, together with the group as it stands.

func (*Client) HostGroupAddMemberManagerContext added in v0.9.0

func (c *Client) HostGroupAddMemberManagerContext(ctx context.Context, name string, users, groups []string) (*HostGroup, error)

HostGroupAddMemberManagerContext is like HostGroupAddMemberManager but bounds the request with ctx.

func (*Client) HostGroupDelete added in v0.9.0

func (c *Client) HostGroupDelete(names ...string) error

HostGroupDelete deletes host groups with `hostgroup_del`; it requires the Host Group Administrators privilege (System: Remove Hostgroups).

func (*Client) HostGroupDeleteContext added in v0.9.0

func (c *Client) HostGroupDeleteContext(ctx context.Context, names ...string) error

HostGroupDeleteContext is like HostGroupDelete but bounds the request with ctx.

func (*Client) HostGroupFind added in v0.9.0

func (c *Client) HostGroupFind(options Options) ([]*HostGroup, error)

HostGroupFind finds host groups with `hostgroup_find`; options are passed through (e.g. `cn`, `host`, `in_hostgroup`, `sizelimit`). A truncated result comes back with ErrTruncated. Any authenticated user may read host groups (System: Read Hostgroups).

func (*Client) HostGroupFindContext added in v0.9.0

func (c *Client) HostGroupFindContext(ctx context.Context, options Options) ([]*HostGroup, error)

HostGroupFindContext is like HostGroupFind but bounds the request with ctx.

func (*Client) HostGroupRemoveMember added in v0.9.0

func (c *Client) HostGroupRemoveMember(name string, hosts, hostgroups []string) (*HostGroup, error)

HostGroupRemoveMember removes hosts and host groups from a host group with `hostgroup_remove_member`. It needs the Host Group Administrators privilege (System: Modify Hostgroup Membership), or the caller is a member manager of the group; per-member problems are returned as *MemberError, together with the group as it stands.

func (*Client) HostGroupRemoveMemberContext added in v0.9.0

func (c *Client) HostGroupRemoveMemberContext(ctx context.Context, name string, hosts, hostgroups []string) (*HostGroup, error)

HostGroupRemoveMemberContext is like HostGroupRemoveMember but bounds the request with ctx.

func (*Client) HostGroupRemoveMemberManager added in v0.9.0

func (c *Client) HostGroupRemoveMemberManager(name string, users, groups []string) (*HostGroup, error)

HostGroupRemoveMemberManager removes member managers from a host group with `hostgroup_remove_member_manager`; it requires the Host Group Administrators privilege (System: Modify Hostgroups). Per-member problems are returned as *MemberError, together with the group as it stands.

func (*Client) HostGroupRemoveMemberManagerContext added in v0.9.0

func (c *Client) HostGroupRemoveMemberManagerContext(ctx context.Context, name string, users, groups []string) (*HostGroup, error)

HostGroupRemoveMemberManagerContext is like HostGroupRemoveMemberManager but bounds the request with ctx.

func (*Client) HostGroupShow added in v0.9.0

func (c *Client) HostGroupShow(name string) (*HostGroup, error)

HostGroupShow fetches a host group with `hostgroup_show`. Any authenticated user may read host groups (System: Read Hostgroups).

func (*Client) HostGroupShowContext added in v0.9.0

func (c *Client) HostGroupShowContext(ctx context.Context, name string) (*HostGroup, error)

HostGroupShowContext is like HostGroupShow but bounds the request with ctx.

func (*Client) HostMod added in v1.1.0

func (c *Client) HostMod(h *Host) (*Host, error)

HostMod changes a host with `host_mod`; it requires the Host Administrators privilege (System: Modify Hosts). It sends description, locality, location, platform, OS version, MAC addresses and user classes as they are in h; an empty value clears the attribute. If nothing changes it returns h itself.

func (*Client) HostModContext added in v1.1.0

func (c *Client) HostModContext(ctx context.Context, h *Host) (*Host, error)

HostModContext is like HostMod but bounds the request with ctx.

func (*Client) HostShow added in v0.4.0

func (c *Client) HostShow(fqdn string) (*Host, error)

HostShow fetches a host with `host_show`. Any authenticated user may read hosts (System: Read Hosts). ubccr/goipa#11.

func (*Client) HostShowContext added in v0.4.0

func (c *Client) HostShowContext(ctx context.Context, fqdn string) (*Host, error)

HostShowContext is like HostShow but bounds the request with ctx.

func (*Client) Login

func (c *Client) Login(username, password string) error

Login to FreeIPA using local kerberos login username and password

Example

Login gets a Kerberos ticket for the password, which later calls authenticate with; it needs /etc/krb5.conf and a KDC, so it is compiled but not run.

package main

import (
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"))
	if err != nil {
		log.Fatal(err)
	}
	if err := c.Login("jesse", "secret"); err != nil {
		log.Fatal(err)
	}
}

func (*Client) LoginFromCCache

func (c *Client) LoginFromCCache(cpath string) error

Login to FreeIPA using credentials cache

Example

LoginFromCCache reuses a ticket obtained with kinit; compiled but not run.

package main

import (
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	if err := c.LoginFromCCache("/tmp/krb5cc_1000"); err != nil {
		log.Fatal(err)
	}
}

func (*Client) LoginFromCCacheData added in v0.6.0

func (c *Client) LoginFromCCacheData(ccache []byte) error

LoginFromCCacheData is like LoginFromCCache but takes the credentials cache contents.

func (*Client) LoginWithKeytab

func (c *Client) LoginWithKeytab(ktab, username string) error

Login to FreeIPA using local kerberos login with keytab and username

func (*Client) LoginWithKeytabData added in v0.6.0

func (c *Client) LoginWithKeytabData(ktab []byte, username string) error

LoginWithKeytabData is like LoginWithKeytab but takes the keytab contents, for containers and secret stores that have no file to point at.

Example

LoginWithKeytabData takes the keytab from memory, for example a secret store; compiled but not run.

package main

import (
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	var keytab []byte // read from a secret store
	var krb5conf []byte

	c, err := ipa.New(
		ipa.WithHost("ipa.example.com"),
		ipa.WithRealm("EXAMPLE.COM"),
		ipa.WithKrb5ConfigData(krb5conf),
	)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.LoginWithKeytabData(keytab, "svc-app"); err != nil {
		log.Fatal(err)
	}
}

func (*Client) Modify added in v0.7.0

func (c *Client) Modify(command string, keys ...string) *Modification

Modify starts a modification with a *_mod command such as "user_mod" of the entry named by keys, the command's positional primary key(s): one for most objects, more for nested ones such as dnsrecord_mod's zone and record name. Nothing is sent until Run.

Example

Modify changes single attributes without reading the object first; compiled but not run.

package main

import (
	"context"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	_, err = c.Modify("user_mod", "jesse").
		Set("title", "Engineer").
		Add("mail", "jesse@example.com").
		Run(context.Background())
	if err != nil {
		log.Fatal(err)
	}
}

func (*Client) PermissionFind added in v0.9.0

func (c *Client) PermissionFind(options Options) ([]*Permission, error)

PermissionFind finds permissions with `permission_find`; options are passed through (e.g. `cn`, `type`, `ipapermright`, `sizelimit`). It requires the RBAC Readers privilege (System: Read Permissions); anyone else finds none.

func (*Client) PermissionFindContext added in v0.9.0

func (c *Client) PermissionFindContext(ctx context.Context, options Options) ([]*Permission, error)

PermissionFindContext is like PermissionFind but bounds the request with ctx.

func (*Client) PermissionShow added in v0.9.0

func (c *Client) PermissionShow(name string) (*Permission, error)

PermissionShow fetches a permission with `permission_show`. It requires the RBAC Readers privilege (System: Read Permissions); to anyone else every permission is ErrNotFound.

func (*Client) PermissionShowContext added in v0.9.0

func (c *Client) PermissionShowContext(ctx context.Context, name string) (*Permission, error)

PermissionShowContext is like PermissionShow but bounds the request with ctx.

func (*Client) Ping

func (c *Client) Ping() (*Response, error)

Ping FreeIPA server to check connection

func (*Client) PingContext added in v0.2.0

func (c *Client) PingContext(ctx context.Context) (*Response, error)

PingContext is like Ping but bounds the request with ctx.

func (*Client) PrivilegeFind added in v0.9.0

func (c *Client) PrivilegeFind(options Options) ([]*Privilege, error)

PrivilegeFind finds privileges with `privilege_find`; options are passed through (e.g. `cn`, `description`, `sizelimit`). It requires the RBAC Readers privilege (System: Read Privileges); anyone else finds none.

func (*Client) PrivilegeFindContext added in v0.9.0

func (c *Client) PrivilegeFindContext(ctx context.Context, options Options) ([]*Privilege, error)

PrivilegeFindContext is like PrivilegeFind but bounds the request with ctx.

func (*Client) PrivilegeShow added in v0.9.0

func (c *Client) PrivilegeShow(name string) (*Privilege, error)

PrivilegeShow fetches a privilege with `privilege_show`. It requires the RBAC Readers privilege (System: Read Privileges); to anyone else every privilege is ErrNotFound.

func (*Client) PrivilegeShowContext added in v0.9.0

func (c *Client) PrivilegeShowContext(ctx context.Context, name string) (*Privilege, error)

PrivilegeShowContext is like PrivilegeShow but bounds the request with ctx.

func (*Client) PwPolicyShow added in v0.5.0

func (c *Client) PwPolicyShow(group string) (*PwPolicy, error)

PwPolicyShow fetches the password policy of group with `pwpolicy_show`; "" is the global_policy. It needs the Password Policy Readers or Password Policy Administrator privilege (System: Read Group Password Policy); without it FreeIPA hides the entry and answers ErrNotFound, not ErrACI.

func (*Client) PwPolicyShowContext added in v0.5.0

func (c *Client) PwPolicyShowContext(ctx context.Context, group string) (*PwPolicy, error)

PwPolicyShowContext is like PwPolicyShow but bounds the request with ctx.

func (*Client) RPC added in v0.2.0

func (c *Client) RPC(method string, args []string, options Options) (*Response, error)

RPC calls any FreeIPA command, an escape hatch for commands goipa does not wrap. It uses the client's HTTP client, session or Kerberos credentials and API version. A FreeIPA failure is returned as a bare *IpaError. options is not modified; a "version" in options wins over IpaClientVersion.

Example
package main

import (
	"fmt"
	"log"

	"github.com/neverlless/goipa/ipatest"
)

func main() {
	s := ipatest.New()
	defer s.Close()

	res, err := s.ClientAs("admin").RPC("ping", nil, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Principal, res.Version)
}
Output:
admin@TEST.LOCAL 4.13.4

func (*Client) RPCContext added in v0.2.0

func (c *Client) RPCContext(ctx context.Context, method string, args []string, options Options) (*Response, error)

RPCContext is like RPC but ends the request when ctx is done.

func (*Client) Realm

func (c *Client) Realm() string

Returns FreeIPA realm

func (*Client) RemoteLogin

func (c *Client) RemoteLogin(uid, passwd string) error

Login to FreeIPA using web API with uid/passwd and set the FreeIPA session id on the client for subsequent requests.

Example

RemoteLogin posts the password to /ipa/session/login_password. Its session ID can be stored, for example in a web session, and reused later without logging in again; compiled but not run.

package main

import (
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	if err := c.RemoteLogin("jesse", "secret"); err != nil {
		log.Fatal(err)
	}
	sid := c.SessionID()

	later, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	later.SetSessionID(sid)
	u, err := later.UserShow("jesse")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Username)
}

func (*Client) RemoteLoginContext added in v0.2.0

func (c *Client) RemoteLoginContext(ctx context.Context, uid, passwd string) error

RemoteLoginContext is like RemoteLogin but bounds the request with ctx.

func (*Client) RemoveOTPToken

func (c *Client) RemoveOTPToken(tokenUUID string) error

Remove OTP token

func (*Client) RemoveOTPTokenContext added in v0.2.0

func (c *Client) RemoveOTPTokenContext(ctx context.Context, tokenUUID string) error

RemoveOTPTokenContext is like RemoveOTPToken but bounds the request with ctx.

func (*Client) ResetPassword

func (c *Client) ResetPassword(username string) (string, error)

Reset user password and return new random password

func (*Client) ResetPasswordContext added in v0.2.0

func (c *Client) ResetPasswordContext(ctx context.Context, username string) (string, error)

ResetPasswordContext is like ResetPassword but bounds the request with ctx.

func (*Client) RoleFind added in v0.9.0

func (c *Client) RoleFind(options Options) ([]*Role, error)

RoleFind finds roles with `role_find`; options are passed through (e.g. `cn`, `description`, `sizelimit`). It requires the RBAC Readers privilege (System: Read Roles); anyone else finds no roles.

func (*Client) RoleFindContext added in v0.9.0

func (c *Client) RoleFindContext(ctx context.Context, options Options) ([]*Role, error)

RoleFindContext is like RoleFind but bounds the request with ctx.

func (*Client) RoleShow added in v0.9.0

func (c *Client) RoleShow(name string) (*Role, error)

RoleShow fetches a role with `role_show`. It requires the RBAC Readers privilege (System: Read Roles); to anyone else every role is ErrNotFound.

func (*Client) RoleShowContext added in v0.9.0

func (c *Client) RoleShowContext(ctx context.Context, name string) (*Role, error)

RoleShowContext is like RoleShow but bounds the request with ctx.

func (*Client) ServerVersion added in v0.7.0

func (c *Client) ServerVersion() string

ServerVersion returns the FreeIPA release from the last successful response that carried one (e.g. 4.13.4), or "" before the first call; call Ping to learn it.

func (*Client) ServiceAdd added in v0.9.0

func (c *Client) ServiceAdd(principal string, force bool) (*Service, error)

ServiceAdd creates a service with `service_add` for a host FreeIPA already knows; it requires the Service Administrators privilege (System: Add Services). force skips FreeIPA's DNS check of the host.

func (*Client) ServiceAddContext added in v0.9.0

func (c *Client) ServiceAddContext(ctx context.Context, principal string, force bool) (*Service, error)

ServiceAddContext is like ServiceAdd but bounds the request with ctx.

func (*Client) ServiceAddHost added in v0.9.0

func (c *Client) ServiceAddHost(principal string, hosts []string) (*Service, error)

ServiceAddHost lets hosts manage a service (managedby) with `service_add_host`; no FreeIPA permission grants writing a service's managedby, so it needs an admin. Per-host problems come back as *MemberError with the service as it stands.

func (*Client) ServiceAddHostContext added in v0.9.0

func (c *Client) ServiceAddHostContext(ctx context.Context, principal string, hosts []string) (*Service, error)

ServiceAddHostContext is like ServiceAddHost but bounds the request with ctx.

func (*Client) ServiceAllowCreateKeytab added in v0.9.0

func (c *Client) ServiceAllowCreateKeytab(principal string, a KeytabAccess) (*Service, error)

ServiceAllowCreateKeytab lets a's users, groups, hosts and host groups create (and so reset) the service's keys with `service_allow_create_keytab`; it requires the Service Administrators privilege (System: Manage Service Keytab Permissions). Per-member problems come back as *MemberError with the service as it stands.

func (*Client) ServiceAllowCreateKeytabContext added in v0.9.0

func (c *Client) ServiceAllowCreateKeytabContext(ctx context.Context, principal string, a KeytabAccess) (*Service, error)

ServiceAllowCreateKeytabContext is like ServiceAllowCreateKeytab but bounds the request with ctx.

func (*Client) ServiceAllowRetrieveKeytab added in v0.9.0

func (c *Client) ServiceAllowRetrieveKeytab(principal string, a KeytabAccess) (*Service, error)

ServiceAllowRetrieveKeytab lets a's users, groups, hosts and host groups retrieve the service's keytab with `service_allow_retrieve_keytab`; it requires the Service Administrators privilege (System: Manage Service Keytab Permissions). Per-member problems come back as *MemberError with the service as it stands.

func (*Client) ServiceAllowRetrieveKeytabContext added in v0.9.0

func (c *Client) ServiceAllowRetrieveKeytabContext(ctx context.Context, principal string, a KeytabAccess) (*Service, error)

ServiceAllowRetrieveKeytabContext is like ServiceAllowRetrieveKeytab but bounds the request with ctx.

func (*Client) ServiceDelete added in v0.9.0

func (c *Client) ServiceDelete(principals ...string) error

ServiceDelete deletes services with `service_del`; it requires the Service Administrators privilege (System: Remove Services).

func (*Client) ServiceDeleteContext added in v0.9.0

func (c *Client) ServiceDeleteContext(ctx context.Context, principals ...string) error

ServiceDeleteContext is like ServiceDelete but bounds the request with ctx.

func (*Client) ServiceDisable added in v0.9.0

func (c *Client) ServiceDisable(principal string) error

ServiceDisable removes a service's keys, and revokes and removes the certificates FreeIPA's CA issued it, with `service_disable`; it requires the Service Administrators privilege (System: Manage Service Keytab). Before FreeIPA 4.13 certificates from elsewhere stay, and a service with neither keys nor CA-issued certificates is the server's *IpaError 4010 (AlreadyInactive); 4.13 removes those certificates too.

func (*Client) ServiceDisableContext added in v0.9.0

func (c *Client) ServiceDisableContext(ctx context.Context, principal string) error

ServiceDisableContext is like ServiceDisable but bounds the request with ctx.

func (*Client) ServiceDisallowCreateKeytab added in v0.9.0

func (c *Client) ServiceDisallowCreateKeytab(principal string, a KeytabAccess) (*Service, error)

ServiceDisallowCreateKeytab revokes what ServiceAllowCreateKeytab granted, with `service_disallow_create_keytab`; it requires the Service Administrators privilege (System: Manage Service Keytab Permissions). Per-member problems come back as *MemberError with the service as it stands.

func (*Client) ServiceDisallowCreateKeytabContext added in v0.9.0

func (c *Client) ServiceDisallowCreateKeytabContext(ctx context.Context, principal string, a KeytabAccess) (*Service, error)

ServiceDisallowCreateKeytabContext is like ServiceDisallowCreateKeytab but bounds the request with ctx.

func (*Client) ServiceDisallowRetrieveKeytab added in v0.9.0

func (c *Client) ServiceDisallowRetrieveKeytab(principal string, a KeytabAccess) (*Service, error)

ServiceDisallowRetrieveKeytab revokes what ServiceAllowRetrieveKeytab granted, with `service_disallow_retrieve_keytab`; it requires the Service Administrators privilege (System: Manage Service Keytab Permissions). Per-member problems come back as *MemberError with the service as it stands.

func (*Client) ServiceDisallowRetrieveKeytabContext added in v0.9.0

func (c *Client) ServiceDisallowRetrieveKeytabContext(ctx context.Context, principal string, a KeytabAccess) (*Service, error)

ServiceDisallowRetrieveKeytabContext is like ServiceDisallowRetrieveKeytab but bounds the request with ctx.

func (*Client) ServiceFind added in v0.9.0

func (c *Client) ServiceFind(options Options) ([]*Service, error)

ServiceFind finds services with `service_find`; options are passed through (e.g. `krbcanonicalname`, `man_by_host`, `sizelimit`). A truncated result comes back with ErrTruncated. Any authenticated user may read services (System: Read Services).

func (*Client) ServiceFindContext added in v0.9.0

func (c *Client) ServiceFindContext(ctx context.Context, options Options) ([]*Service, error)

ServiceFindContext is like ServiceFind but bounds the request with ctx.

func (*Client) ServiceRemoveHost added in v0.9.0

func (c *Client) ServiceRemoveHost(principal string, hosts []string) (*Service, error)

ServiceRemoveHost stops hosts managing a service with `service_remove_host`; no FreeIPA permission grants writing a service's managedby, so it needs an admin. Per-host problems come back as *MemberError with the service as it stands.

func (*Client) ServiceRemoveHostContext added in v0.9.0

func (c *Client) ServiceRemoveHostContext(ctx context.Context, principal string, hosts []string) (*Service, error)

ServiceRemoveHostContext is like ServiceRemoveHost but bounds the request with ctx.

func (*Client) ServiceShow added in v0.9.0

func (c *Client) ServiceShow(principal string) (*Service, error)

ServiceShow fetches a service with `service_show`; the realm may be left out of principal. Any authenticated user may read services (System: Read Services).

func (*Client) ServiceShowContext added in v0.9.0

func (c *Client) ServiceShowContext(ctx context.Context, principal string) (*Service, error)

ServiceShowContext is like ServiceShow but bounds the request with ctx.

func (*Client) SessionID

func (c *Client) SessionID() string

Return current FreeIPA sessionID

func (*Client) SetAuthTypes

func (c *Client) SetAuthTypes(username string, types []string) error

Update user authentication types.

func (*Client) SetAuthTypesContext added in v0.2.0

func (c *Client) SetAuthTypesContext(ctx context.Context, username string, types []string) error

SetAuthTypesContext is like SetAuthTypes but bounds the request with ctx.

func (*Client) SetPassword

func (c *Client) SetPassword(username, oldPasswd, newPasswd, otpcode string) error

Set user password. In FreeIPA when a password is first set or when a password is later reset it is marked as immediately expired and requires the owner to perform a password change. See here https://www.freeipa.org/page/New_Passwords_Expired for more details. This function exists to circumvent the "new passwords expired" feature of FreeIPA and allow an administrator to set a new password for a user without it being expired. This is acheived, for example, by first calling ResetPassword() then immediately calling this function. *WARNING* See https://www.freeipa.org/page/Self-Service_Password_Reset for security issues and possible weaknesses of this approach.

Unlike ChangePassword, it uses the form endpoint and needs no session.

func (*Client) SetPasswordContext added in v0.2.0

func (c *Client) SetPasswordContext(ctx context.Context, username, oldPasswd, newPasswd, otpcode string) error

SetPasswordContext is like SetPassword but bounds the request with ctx.

func (*Client) SetSessionID added in v0.2.0

func (c *Client) SetSessionID(sessionID string)

SetSessionID restores a session saved from SessionID (for example in a web session store) on any client. An empty string clears it.

func (*Client) StageUserActivate added in v0.5.0

func (c *Client) StageUserActivate(username string) (*User, error)

StageUserActivate activates a stage user with `stageuser_activate` and returns the new active user. It requires the Stage User Administrators and User Administrators privileges. If an active user with that name exists, FreeIPA answers ErrDuplicateEntry and keeps the stage entry.

func (*Client) StageUserActivateContext added in v0.5.0

func (c *Client) StageUserActivateContext(ctx context.Context, username string) (*User, error)

StageUserActivateContext is like StageUserActivate but bounds the request with ctx.

func (*Client) StageUserAdd added in v0.5.0

func (c *Client) StageUserAdd(user *User) (*User, error)

StageUserAdd adds a stage user with `stageuser_add`. Username, First and Last are required; empty fields are not sent. It requires the Stage User Administrators privilege (add also: Stage User Provisioning). A duplicate returns the bare *IpaError (ErrDuplicateEntry), not ErrUserExists.

func (*Client) StageUserAddContext added in v0.5.0

func (c *Client) StageUserAddContext(ctx context.Context, user *User) (*User, error)

StageUserAddContext is like StageUserAdd but bounds the request with ctx.

func (*Client) StageUserAddWithPassword added in v1.1.0

func (c *Client) StageUserAddWithPassword(user *User, password string) (*User, error)

StageUserAddWithPassword is like StageUserAdd but sets the password in the same call (`userpassword`), which StageUserActivate keeps. It is a separate call, not a field on User, because User.ToOptions would then send the password with every add and mod.

func (*Client) StageUserAddWithPasswordContext added in v1.1.0

func (c *Client) StageUserAddWithPasswordContext(ctx context.Context, user *User, password string) (*User, error)

StageUserAddWithPasswordContext is like StageUserAddWithPassword but bounds the request with ctx.

func (*Client) StageUserDelete added in v0.5.0

func (c *Client) StageUserDelete(usernames ...string) error

StageUserDelete deletes stage users with `stageuser_del`, stopping at the first error. It requires the Stage User Administrators privilege.

func (*Client) StageUserDeleteContext added in v0.5.0

func (c *Client) StageUserDeleteContext(ctx context.Context, usernames ...string) error

StageUserDeleteContext is like StageUserDelete but bounds the request with ctx.

func (*Client) StageUserFind added in v0.5.0

func (c *Client) StageUserFind(options Options) ([]*User, error)

StageUserFind finds stage users with `stageuser_find`; options are passed through (e.g. `uid`, `sizelimit`). It requires the Stage User Administrators privilege.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) StageUserFindContext added in v0.5.0

func (c *Client) StageUserFindContext(ctx context.Context, options Options) ([]*User, error)

StageUserFindContext is like StageUserFind but bounds the request with ctx.

func (*Client) StageUserMod added in v0.5.0

func (c *Client) StageUserMod(user *User) (*User, error)

StageUserMod modifies a stage user with `stageuser_mod`, sending the same attributes as UserMod; like UserMod it is read-modify-write, so start from StageUserShow. It returns user itself when nothing changed. It requires the Stage User Administrators privilege.

func (*Client) StageUserModContext added in v0.5.0

func (c *Client) StageUserModContext(ctx context.Context, user *User) (*User, error)

StageUserModContext is like StageUserMod but bounds the request with ctx.

func (*Client) StageUserShow added in v0.5.0

func (c *Client) StageUserShow(username string) (*User, error)

StageUserShow fetches a stage user with `stageuser_show`. It requires the Stage User Administrators privilege.

func (*Client) StageUserShowContext added in v0.5.0

func (c *Client) StageUserShowContext(ctx context.Context, username string) (*User, error)

StageUserShowContext is like StageUserShow but bounds the request with ctx.

func (*Client) StickySession

func (c *Client) StickySession(enable bool)

Set stick sessions.

func (*Client) SubIDFind added in v0.5.0

func (c *Client) SubIDFind(options Options) ([]*SubID, error)

SubIDFind finds sub-ID ranges with `subid_find`; options are passed through (e.g. `ipaowner`). Any authenticated user may read sub-IDs. FreeIPA 4.9.7+; ErrNotSupported when the server version is known to be older.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) SubIDFindContext added in v0.5.0

func (c *Client) SubIDFindContext(ctx context.Context, options Options) ([]*SubID, error)

SubIDFindContext is like SubIDFind but bounds the request with ctx.

func (*Client) SubIDGenerate added in v0.5.0

func (c *Client) SubIDGenerate(owner string) (*SubID, error)

SubIDGenerate allocates a range with `subid_generate`; owner "" means the caller. For yourself it needs the Subordinate ID Selfservice User role, for others Subordinate ID Administrators. One range per user: a second call returns ErrDuplicateEntry. Servers older than 4.9.7 give ErrNotSupported when their version is known. A server with sub-IDs disabled returns a 3009 ValidationError.

func (*Client) SubIDGenerateContext added in v0.5.0

func (c *Client) SubIDGenerateContext(ctx context.Context, owner string) (*SubID, error)

SubIDGenerateContext is like SubIDGenerate but bounds the request with ctx.

func (*Client) SudoRuleAdd added in v0.9.0

func (c *Client) SudoRuleAdd(r *SudoRule) (*SudoRule, error)

SudoRuleAdd creates a sudo rule with `sudorule_add` from r's name, description, the categories set to "all" and Order when positive (FreeIPA rejects an order another rule uses). New rules are enabled; r.Enabled is ignored. Members and options are added with the SudoRuleAdd* calls. It needs the Sudo Administrator privilege (System: Add Sudo rule).

func (*Client) SudoRuleAddAllowCommand added in v0.9.0

func (c *Client) SudoRuleAddAllowCommand(name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleAddAllowCommand allows sudo commands and command groups in a sudo rule with `sudorule_add_allow_command`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddAllowCommandContext added in v0.9.0

func (c *Client) SudoRuleAddAllowCommandContext(ctx context.Context, name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleAddAllowCommandContext is like SudoRuleAddAllowCommand but bounds the request with ctx.

func (*Client) SudoRuleAddContext added in v0.9.0

func (c *Client) SudoRuleAddContext(ctx context.Context, r *SudoRule) (*SudoRule, error)

SudoRuleAddContext is like SudoRuleAdd but bounds the request with ctx.

func (*Client) SudoRuleAddDenyCommand added in v0.9.0

func (c *Client) SudoRuleAddDenyCommand(name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleAddDenyCommand denies sudo commands and command groups in a sudo rule with `sudorule_add_deny_command`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddDenyCommandContext added in v0.9.0

func (c *Client) SudoRuleAddDenyCommandContext(ctx context.Context, name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleAddDenyCommandContext is like SudoRuleAddDenyCommand but bounds the request with ctx.

func (*Client) SudoRuleAddHost added in v0.9.0

func (c *Client) SudoRuleAddHost(name string, hosts, hostgroups []string) (*SudoRule, error)

SudoRuleAddHost adds hosts and host groups to a sudo rule with `sudorule_add_host`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddHostContext added in v0.9.0

func (c *Client) SudoRuleAddHostContext(ctx context.Context, name string, hosts, hostgroups []string) (*SudoRule, error)

SudoRuleAddHostContext is like SudoRuleAddHost but bounds the request with ctx.

func (*Client) SudoRuleAddOption added in v0.9.0

func (c *Client) SudoRuleAddOption(name string, options ...string) (*SudoRule, error)

SudoRuleAddOption adds sudoers options (ipasudoopt, e.g. "!authenticate") to a sudo rule with `sudorule_add_option`. An option the rule already has fails with FreeIPA's DuplicateEntry (4002). Each option is its own request, in order, as FreeIPA 4.9 takes one per call; the first failure stops the rest, leaving the earlier options added. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddOptionContext added in v0.9.0

func (c *Client) SudoRuleAddOptionContext(ctx context.Context, name string, options ...string) (*SudoRule, error)

SudoRuleAddOptionContext is like SudoRuleAddOption but bounds the request with ctx.

func (*Client) SudoRuleAddRunAsGroup added in v0.9.0

func (c *Client) SudoRuleAddRunAsGroup(name string, groups []string) (*SudoRule, error)

SudoRuleAddRunAsGroup lets a sudo rule run commands with the gid of groups with `sudorule_add_runasgroup`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddRunAsGroupContext added in v0.9.0

func (c *Client) SudoRuleAddRunAsGroupContext(ctx context.Context, name string, groups []string) (*SudoRule, error)

SudoRuleAddRunAsGroupContext is like SudoRuleAddRunAsGroup but bounds the request with ctx.

func (*Client) SudoRuleAddRunAsUser added in v0.9.0

func (c *Client) SudoRuleAddRunAsUser(name string, users, groups []string) (*SudoRule, error)

SudoRuleAddRunAsUser lets a sudo rule run commands as users and as members of groups with `sudorule_add_runasuser`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddRunAsUserContext added in v0.9.0

func (c *Client) SudoRuleAddRunAsUserContext(ctx context.Context, name string, users, groups []string) (*SudoRule, error)

SudoRuleAddRunAsUserContext is like SudoRuleAddRunAsUser but bounds the request with ctx.

func (*Client) SudoRuleAddUser added in v0.9.0

func (c *Client) SudoRuleAddUser(name string, users, groups []string) (*SudoRule, error)

SudoRuleAddUser adds users and groups to a sudo rule with `sudorule_add_user`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleAddUserContext added in v0.9.0

func (c *Client) SudoRuleAddUserContext(ctx context.Context, name string, users, groups []string) (*SudoRule, error)

SudoRuleAddUserContext is like SudoRuleAddUser but bounds the request with ctx.

func (*Client) SudoRuleDelete added in v0.9.0

func (c *Client) SudoRuleDelete(names ...string) error

SudoRuleDelete deletes sudo rules with `sudorule_del`. It needs the Sudo Administrator privilege (System: Delete Sudo rule).

func (*Client) SudoRuleDeleteContext added in v0.9.0

func (c *Client) SudoRuleDeleteContext(ctx context.Context, names ...string) error

SudoRuleDeleteContext is like SudoRuleDelete but bounds the request with ctx.

func (*Client) SudoRuleDisable added in v0.9.0

func (c *Client) SudoRuleDisable(name string) error

SudoRuleDisable disables a sudo rule with `sudorule_disable`. Disabling a disabled rule succeeds. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleDisableContext added in v0.9.0

func (c *Client) SudoRuleDisableContext(ctx context.Context, name string) error

SudoRuleDisableContext is like SudoRuleDisable but bounds the request with ctx.

func (*Client) SudoRuleEnable added in v0.9.0

func (c *Client) SudoRuleEnable(name string) error

SudoRuleEnable enables a sudo rule with `sudorule_enable`. Enabling an enabled rule succeeds. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleEnableContext added in v0.9.0

func (c *Client) SudoRuleEnableContext(ctx context.Context, name string) error

SudoRuleEnableContext is like SudoRuleEnable but bounds the request with ctx.

func (*Client) SudoRuleFind added in v0.5.0

func (c *Client) SudoRuleFind(options Options) ([]*SudoRule, error)

SudoRuleFind finds sudo rules with `sudorule_find`; options are passed through (e.g. `cn`, `ipaenabledflag`, `sizelimit`). Any authenticated user may read rules (System: Read Sudo Rules). FreeIPA returns at most its search limit (100 by default) unless `sizelimit` is set.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) SudoRuleFindContext added in v0.5.0

func (c *Client) SudoRuleFindContext(ctx context.Context, options Options) ([]*SudoRule, error)

SudoRuleFindContext is like SudoRuleFind but bounds the request with ctx.

func (*Client) SudoRuleRemoveAllowCommand added in v0.9.0

func (c *Client) SudoRuleRemoveAllowCommand(name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleRemoveAllowCommand removes allowed sudo commands and command groups from a sudo rule with `sudorule_remove_allow_command`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveAllowCommandContext added in v0.9.0

func (c *Client) SudoRuleRemoveAllowCommandContext(ctx context.Context, name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleRemoveAllowCommandContext is like SudoRuleRemoveAllowCommand but bounds the request with ctx.

func (*Client) SudoRuleRemoveDenyCommand added in v0.9.0

func (c *Client) SudoRuleRemoveDenyCommand(name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleRemoveDenyCommand removes denied sudo commands and command groups from a sudo rule with `sudorule_remove_deny_command`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveDenyCommandContext added in v0.9.0

func (c *Client) SudoRuleRemoveDenyCommandContext(ctx context.Context, name string, cmds, cmdgroups []string) (*SudoRule, error)

SudoRuleRemoveDenyCommandContext is like SudoRuleRemoveDenyCommand but bounds the request with ctx.

func (*Client) SudoRuleRemoveHost added in v0.9.0

func (c *Client) SudoRuleRemoveHost(name string, hosts, hostgroups []string) (*SudoRule, error)

SudoRuleRemoveHost removes hosts and host groups from a sudo rule with `sudorule_remove_host`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveHostContext added in v0.9.0

func (c *Client) SudoRuleRemoveHostContext(ctx context.Context, name string, hosts, hostgroups []string) (*SudoRule, error)

SudoRuleRemoveHostContext is like SudoRuleRemoveHost but bounds the request with ctx.

func (*Client) SudoRuleRemoveOption added in v0.9.0

func (c *Client) SudoRuleRemoveOption(name string, options ...string) (*SudoRule, error)

SudoRuleRemoveOption removes sudoers options from a sudo rule with `sudorule_remove_option`. An option the rule does not have fails the call with FreeIPA's AttrValueNotFound (4026). Each option is its own request, in order, as FreeIPA 4.9 takes one per call; the first failure stops the rest, leaving the earlier options removed. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveOptionContext added in v0.9.0

func (c *Client) SudoRuleRemoveOptionContext(ctx context.Context, name string, options ...string) (*SudoRule, error)

SudoRuleRemoveOptionContext is like SudoRuleRemoveOption but bounds the request with ctx.

func (*Client) SudoRuleRemoveRunAsGroup added in v0.9.0

func (c *Client) SudoRuleRemoveRunAsGroup(name string, groups []string) (*SudoRule, error)

SudoRuleRemoveRunAsGroup removes run-as groups from a sudo rule with `sudorule_remove_runasgroup`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveRunAsGroupContext added in v0.9.0

func (c *Client) SudoRuleRemoveRunAsGroupContext(ctx context.Context, name string, groups []string) (*SudoRule, error)

SudoRuleRemoveRunAsGroupContext is like SudoRuleRemoveRunAsGroup but bounds the request with ctx.

func (*Client) SudoRuleRemoveRunAsUser added in v0.9.0

func (c *Client) SudoRuleRemoveRunAsUser(name string, users, groups []string) (*SudoRule, error)

SudoRuleRemoveRunAsUser removes run-as users and groups from a sudo rule with `sudorule_remove_runasuser`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveRunAsUserContext added in v0.9.0

func (c *Client) SudoRuleRemoveRunAsUserContext(ctx context.Context, name string, users, groups []string) (*SudoRule, error)

SudoRuleRemoveRunAsUserContext is like SudoRuleRemoveRunAsUser but bounds the request with ctx.

func (*Client) SudoRuleRemoveUser added in v0.9.0

func (c *Client) SudoRuleRemoveUser(name string, users, groups []string) (*SudoRule, error)

SudoRuleRemoveUser removes users and groups from a sudo rule with `sudorule_remove_user`. Per-member problems are returned as *MemberError, together with the rule as it stands. It needs the Sudo Administrator privilege (System: Modify Sudo rule).

func (*Client) SudoRuleRemoveUserContext added in v0.9.0

func (c *Client) SudoRuleRemoveUserContext(ctx context.Context, name string, users, groups []string) (*SudoRule, error)

SudoRuleRemoveUserContext is like SudoRuleRemoveUser but bounds the request with ctx.

func (*Client) SudoRuleShow added in v0.9.0

func (c *Client) SudoRuleShow(name string) (*SudoRule, error)

SudoRuleShow returns a sudo rule with `sudorule_show`. Any authenticated user may read rules (System: Read Sudo Rules).

func (*Client) SudoRuleShowContext added in v0.9.0

func (c *Client) SudoRuleShowContext(ctx context.Context, name string) (*SudoRule, error)

SudoRuleShowContext is like SudoRuleShow but bounds the request with ctx.

func (*Client) SyncOTPToken added in v0.5.0

func (c *Client) SyncOTPToken(username, password, firstCode, secondCode, tokenID string) error

SyncOTPToken resynchronises an OTP token whose clock or counter drifted, from two consecutive codes, through /ipa/session/sync_token. password is the user's password without an OTP. tokenID selects the token (unique ID or DN); "" lets the server try the user's tokens. No session or Kerberos ticket is needed. Based on ubccr/goipa#2 by @farzandalaee.

func (*Client) SyncOTPTokenContext added in v0.5.0

func (c *Client) SyncOTPTokenContext(ctx context.Context, username, password, firstCode, secondCode, tokenID string) error

SyncOTPTokenContext is like SyncOTPToken but bounds the request with ctx.

func (*Client) UserAdd

func (c *Client) UserAdd(user *User, random bool) (*User, error)

Add new user. If random is true a random password will be created for the user. Note this requires "User Administrators" Privilege in FreeIPA.

func (*Client) UserAddContext added in v0.2.0

func (c *Client) UserAddContext(ctx context.Context, user *User, random bool) (*User, error)

UserAddContext is like UserAdd but bounds the request with ctx.

func (*Client) UserAddPasskey added in v0.5.0

func (c *Client) UserAddPasskey(username, mapping string) error

UserAddPasskey adds a passkey mapping with `user_add_passkey`. The mapping is passkey:<credential id b64>,<public key b64 SPKI>[,<user id>]. Users may manage their own mappings; for others the Passkey Administrators privilege is needed. FreeIPA 4.11+: when the server version is known to be older it returns ErrNotSupported without sending (see ServerVersion). A duplicate returns 4038, an invalid mapping 3009. Read mappings with UserShow (User.Passkeys).

func (*Client) UserAddPasskeyContext added in v0.5.0

func (c *Client) UserAddPasskeyContext(ctx context.Context, username, mapping string) error

UserAddPasskeyContext is like UserAddPasskey but bounds the request with ctx.

func (*Client) UserAddWithPassword

func (c *Client) UserAddWithPassword(user *User, password string) (*User, error)

Add new user and set password. Note this requires "User Administrators" Privilege in FreeIPA.

func (*Client) UserAddWithPasswordContext added in v0.2.0

func (c *Client) UserAddWithPasswordContext(ctx context.Context, user *User, password string) (*User, error)

UserAddWithPasswordContext is like UserAddWithPassword but bounds the request with ctx.

func (*Client) UserDelete

func (c *Client) UserDelete(preserve, stopOnError bool, usernames ...string) error

Delete user. If preserve is false the user will be permanetly deleted, if true the users is moved to the Delete container. If stopOnError is false the operation will be in continuous mode otherwise it will stop on errors

stopOnError=false is FreeIPA's continue=true; other Delete calls always stop on the first error.

func (*Client) UserDeleteContext added in v0.2.0

func (c *Client) UserDeleteContext(ctx context.Context, preserve, stopOnError bool, usernames ...string) error

UserDeleteContext is like UserDelete but bounds the request with ctx.

func (*Client) UserDisable

func (c *Client) UserDisable(username string) error

Disable User Account

func (*Client) UserDisableContext added in v0.2.0

func (c *Client) UserDisableContext(ctx context.Context, username string) error

UserDisableContext is like UserDisable but bounds the request with ctx.

func (*Client) UserEnable

func (c *Client) UserEnable(username string) error

Enable User Account

func (*Client) UserEnableContext added in v0.2.0

func (c *Client) UserEnableContext(ctx context.Context, username string) error

UserEnableContext is like UserEnable but bounds the request with ctx.

func (*Client) UserFind

func (c *Client) UserFind(options Options) ([]*User, error)

Find users.

A truncated search is not reported unless the Client was built WithTruncationErrors; FindEntries reports it too.

func (*Client) UserFindContext added in v0.2.0

func (c *Client) UserFindContext(ctx context.Context, options Options) ([]*User, error)

UserFindContext is like UserFind but bounds the request with ctx.

func (*Client) UserMod

func (c *Client) UserMod(user *User) (*User, error)

Modify user. It is read-modify-write: send a User from UserShow with the changes, as every attribute ToOptions sends is set, an empty HomeDir included (FreeIPA rejects that with 4205). Currently only modifies a subset of user attributes: mail (all values, see Emails), givenname, sn, homedirectory, loginshell, displayname, ipasshpubkey, telephonenumber, and mobile

func (*Client) UserModContext added in v0.2.0

func (c *Client) UserModContext(ctx context.Context, user *User) (*User, error)

UserModContext is like UserMod but bounds the request with ctx.

func (*Client) UserPwPolicy added in v0.5.0

func (c *Client) UserPwPolicy(username string) (*PwPolicy, error)

UserPwPolicy fetches the policy that applies to username with `pwpolicy_show` and its `user` option: the group policy with the lowest priority among the user's groups, else the global policy. FreeIPA resolves it as the caller, so the caller must be able to read the user, and, as for PwPolicyShow, a caller without the privilege gets ErrNotFound. Priority is 0 because FreeIPA does not return it here.

func (*Client) UserPwPolicyContext added in v0.5.0

func (c *Client) UserPwPolicyContext(ctx context.Context, username string) (*PwPolicy, error)

UserPwPolicyContext is like UserPwPolicy but bounds the request with ctx.

func (*Client) UserRemovePasskey added in v0.5.0

func (c *Client) UserRemovePasskey(username, mapping string) error

UserRemovePasskey removes a passkey mapping with `user_remove_passkey`; see UserAddPasskey. A mapping that is not present returns 4026.

func (*Client) UserRemovePasskeyContext added in v0.5.0

func (c *Client) UserRemovePasskeyContext(ctx context.Context, username, mapping string) error

UserRemovePasskeyContext is like UserRemovePasskey but bounds the request with ctx.

func (*Client) UserShow

func (c *Client) UserShow(username string) (*User, error)

Fetch user details by call the FreeIPA user-show method

func (*Client) UserShowContext added in v0.2.0

func (c *Client) UserShowContext(ctx context.Context, username string) (*User, error)

UserShowContext is like UserShow but bounds the request with ctx.

func (*Client) UserStatus added in v0.5.0

func (c *Client) UserStatus(username string) ([]*ReplicaStatus, error)

UserStatus reports a user's failed logins with `user_status`; one entry per master, each master is queried live. Without the User Administrators privilege FreeIPA hides the counters (FailedLogins 0, zero times) instead of failing.

func (*Client) UserStatusContext added in v0.5.0

func (c *Client) UserStatusContext(ctx context.Context, username string) ([]*ReplicaStatus, error)

UserStatusContext is like UserStatus but bounds the request with ctx.

func (*Client) UserUnlock added in v0.5.0

func (c *Client) UserUnlock(username string) error

UserUnlock resets a user's failed login counter with `user_unlock`. It requires User Administrators (System: Unlock User). On FreeIPA 4.13 members of admins and trust admins cannot be unlocked through delegation (2100). It writes the local master; replication carries it.

func (*Client) UserUnlockContext added in v0.5.0

func (c *Client) UserUnlockContext(ctx context.Context, username string) error

UserUnlockContext is like UserUnlock but bounds the request with ctx.

func (*Client) WhoAmI added in v0.6.0

func (c *Client) WhoAmI() (*Identity, error)

WhoAmI runs `whoami`: which account the server maps the credentials to. Any authenticated principal may call it; FreeIPA 4.5+.

func (*Client) WhoAmIContext added in v0.6.0

func (c *Client) WhoAmIContext(ctx context.Context) (*Identity, error)

WhoAmIContext is like WhoAmI but bounds the request with ctx.

type Command added in v0.8.0

type Command struct {
	Name    string  // e.g. "user_add"
	Since   string  // first catalogued release with it; "4.9.0" means 4.9.0 or earlier
	Args    []Param // positional, in API.txt order
	Options []Param // in API.txt order
}

Command describes a FreeIPA JSON-RPC command as published in the API.txt of the FreeIPA releases the catalogue was generated from.

func Commands added in v0.8.0

func Commands(version string) []Command

Commands returns the commands a FreeIPA server of the given version has, sorted by name, with only the arguments and options that version has. An empty or unparsable version returns everything catalogued. A version newer than the newest catalogued release gets that release's commands, so commands added after it are not listed.

Example

Commands lists what a server version supports; the sysaccount_* commands came with FreeIPA 4.13.0.

package main

import (
	"fmt"

	ipa "github.com/neverlless/goipa"
)

func main() {
	old := map[string]bool{}
	for _, c := range ipa.Commands("4.12.0") {
		old[c.Name] = true
	}
	for _, c := range ipa.Commands("4.13.0") {
		if !old[c.Name] {
			fmt.Println(c.Name)
		}
	}
}
Output:
sysaccount_add
sysaccount_del
sysaccount_disable
sysaccount_enable
sysaccount_find
sysaccount_mod
sysaccount_policy
sysaccount_show

func LookupCommand added in v0.8.0

func LookupCommand(name, version string) (Command, bool)

LookupCommand returns the named command as Commands(version) would list it, and false when that version does not have it.

type DNSRecord added in v0.9.0

type DNSRecord struct {
	Name string // idnsname, relative ("@" is the apex)
	// Values by upper-case type ("A" holds arecord), from every *record
	// attribute.
	Records map[string][]string
}

DNSRecord is the set of resource records at one name of a zone. Change TTLs and other attributes with Modify("dnsrecord_mod", zone, name).

type DNSZone added in v0.9.0

type DNSZone struct {
	Name       string // idnsname, absolute with trailing dot
	Active     bool   // idnszoneactive
	NameServer string // idnssoamname
	AdminEmail string // idnssoarname, in DNS form, relative to the zone unless it ends in "." ("hostmaster")
	// idnssoaserial, idnssoarefresh, idnssoaretry, idnssoaexpire, idnssoaminimum
	Serial, Refresh, Retry, Expire, Minimum int64
	TTL                                     int64 // dnsttl (0 if unset)
	DynamicUpdate                           bool  // idnsallowdynupdate
}

DNSZone is a master DNS zone of FreeIPA's integrated DNS. Change other attributes with Modify("dnszone_mod", name).

type Entry added in v0.7.0

type Entry struct {
	// contains filtered or unexported fields
}

Entry is one FreeIPA record as the server sent it. The accessors read FreeIPA's encodings (single values in lists, "TRUE" strings, datetime and base64 class hints) so callers need no JSON handling; Raw gives the rest.

func FindEntries added in v0.7.0

func FindEntries(ctx context.Context, c *Client, method string, args []string, opts Options, sizelimit int) ([]Entry, error)

FindEntries runs a *_find command with args as Call sends them (nil sends none; the search criteria is optional in FreeIPA), all: true (unless opts sets all) and sizelimit when it is above 0 (0 keeps the server default). When the server reports the result truncated it returns the entries and ErrTruncated. opts is not modified.

Example

FindEntries returns the entries it got together with ErrTruncated when the server cut the search short; compiled but not run.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	hosts, err := ipa.FindEntries(context.Background(), c, "host_find", []string{"web"}, nil, 500)
	if errors.Is(err, ipa.ErrTruncated) {
		fmt.Println("more hosts match; narrow the search")
	} else if err != nil {
		log.Fatal(err)
	}
	for _, h := range hosts {
		fmt.Println(h.Str("fqdn"))
	}
}

func (Entry) Bool added in v0.7.0

func (e Entry) Bool(attr string) bool

Bool reads true, [true], "TRUE" or ["TRUE"].

func (Entry) Bytes added in v0.7.0

func (e Entry) Bytes(attr string) []byte

Bytes decodes a {"__base64__": ...} hint; nil otherwise.

func (Entry) DN added in v0.7.0

func (e Entry) DN(attr string) string

DN is Str, named for attributes that hold a DN.

func (Entry) Has added in v0.7.0

func (e Entry) Has(attr string) bool

Has reports whether the attribute is present, even as null.

func (Entry) Int added in v0.7.0

func (e Entry) Int(attr string) (int64, bool)

Int parses a number or numeric string; ok is false when absent or not an integer.

func (Entry) MarshalJSON added in v0.7.0

func (e Entry) MarshalJSON() ([]byte, error)

MarshalJSON returns the object the entry was decoded from.

func (Entry) Raw added in v0.7.0

func (e Entry) Raw() json.RawMessage

Raw returns the entry's JSON object; do not modify it.

func (Entry) Str added in v0.7.0

func (e Entry) Str(attr string) string

Str returns the attribute's first value, or "" when absent.

func (Entry) Strs added in v0.7.0

func (e Entry) Strs(attr string) []string

Strs returns all values of the attribute; a scalar is one element. It is nil when the attribute is absent or null. A lone object other than {"__dns_name__"} is returned as its JSON; use Time or Bytes for those hints.

func (Entry) Time added in v0.7.0

func (e Entry) Time(attr string) time.Time

Time reads a {"__datetime__": ...} hint or an RFC 3339 string; the zero time otherwise.

func (*Entry) UnmarshalJSON added in v0.7.0

func (e *Entry) UnmarshalJSON(b []byte) error

UnmarshalJSON keeps a copy of the object.

type Group added in v0.4.0

type Group struct {
	Name, Description, GID string
	// member_user, member_group, memberindirect_user, memberindirect_group
	Users, Groups, IndirectUsers, IndirectGroups []string
	// memberof_group
	MemberOf []string
	// membermanager_user, membermanager_group
	ManagerUsers, ManagerGroups []string
	// External: objectclass has ipaexternalgroup. NonPOSIX: objectclass lacks
	// posixgroup. The zero value is a POSIX group.
	External, NonPOSIX bool
}

Group is a FreeIPA user group.

type HBACRule added in v0.5.0

type HBACRule struct {
	// cn, description
	Name, Description string
	// ipaenabledflag
	Enabled bool
	// usercategory, hostcategory, servicecategory: "all" or ""
	UserCategory, HostCategory, ServiceCategory string
	// memberuser_user, memberuser_group
	Users, Groups []string
	// memberhost_host, memberhost_hostgroup
	Hosts, HostGroups []string
	// memberservice_hbacsvc, memberservice_hbacsvcgroup
	Services, ServiceGroups []string
}

HBACRule is a host-based access control rule. There is no HBACRuleMod: change other attributes with Modify("hbacrule_mod", name).

type HBACTestResult added in v0.5.0

type HBACTestResult struct {
	// value
	Granted bool
	// matched, notmatched: names of the rules that did and did not match
	Matched, NotMatched []string
	// error, warning
	Errors, Warnings []string
}

HBACTestResult is the outcome of HBACTest.

type HTTPError added in v0.2.0

type HTTPError struct {
	StatusCode int
	Status     string
}

HTTPError is returned when the server answers a JSON-RPC call with a status other than 200. HTTP 401 (for example an expired session) also matches ErrUnauthorized with errors.Is.

func (*HTTPError) Error added in v0.2.0

func (e *HTTPError) Error() string

Error returns the message used before HTTPError existed.

func (*HTTPError) Is added in v0.2.0

func (e *HTTPError) Is(target error) bool

Is reports whether target is ErrUnauthorized and the status is 401.

type Host added in v0.4.0

type Host struct {
	// fqdn, description, l, nshostlocation, nshardwareplatform, nsosversion,
	// krbprincipalname (first value of each)
	FQDN, Description, Locality, Location, Platform, OSVersion, Principal string
	// macaddress, userclass
	MACAddresses, UserClass []string
	// memberof_hostgroup, memberofindirect_hostgroup
	HostGroups, IndirectHostGroups []string
	// managedby_host
	ManagedBy []string
	// has_keytab, has_password
	HasKeytab, HasPassword bool
	// randompassword, set only by an add with random
	RandomPassword string
}

Host is a FreeIPA host.

type HostGroup added in v0.9.0

type HostGroup struct {
	Name, Description string // cn, description
	// member_host, member_hostgroup, memberindirect_host, memberindirect_hostgroup
	Hosts, HostGroups, IndirectHosts, IndirectHostGroups []string
	MemberOf                                             []string // memberof_hostgroup
	ManagerUsers, ManagerGroups                          []string // membermanager_user, membermanager_group
}

HostGroup is a FreeIPA host group. Attribute changes go through Modify ("hostgroup_mod").

type Identity added in v0.6.0

type Identity struct {
	// object: "user", "host", "service" or "idoverrideuser"
	Object string
	// command, as sent: "user_show/1"
	Command string
	// arguments: the primary key(s), e.g. ["admin"]
	Arguments []string
}

Identity is the account the server sees for the current credentials.

type IpaError

type IpaError struct {
	Message string
	Code    int
	Name    string `json:"name"`
	// Data is the raw JSON of the exception's keyword arguments, e.g.
	// {"reason":"..."}. A string so IpaError stays comparable.
	Data string `json:"data"`
}

FreeIPA error

func (*IpaError) Error

func (e *IpaError) Error() string

func (*IpaError) Is added in v0.2.0

func (e *IpaError) Is(target error) bool

Is reports whether target is an *IpaError with the same Code.

func (*IpaError) MarshalJSON added in v0.3.0

func (e *IpaError) MarshalJSON() ([]byte, error)

MarshalJSON writes FreeIPA's error shape; an empty or non-JSON Data becomes {}.

func (*IpaError) UnmarshalJSON added in v0.2.0

func (e *IpaError) UnmarshalJSON(b []byte) error

UnmarshalJSON keeps Data as raw JSON text; Message and Code still match the "message" and "code" keys case-insensitively.

type KeytabAccess added in v0.9.0

type KeytabAccess struct{ Users, Groups, Hosts, HostGroups []string }

KeytabAccess lists who may retrieve or create a service's keytab.

type MemberError added in v0.4.0

type MemberError struct {
	Failures []MemberFailure
}

MemberError reports the members a member call could not change. FreeIPA lists them in the result, with no error, even when the caller lacks the right to change members at all.

func (*MemberError) Error added in v0.4.0

func (e *MemberError) Error() string

type MemberFailure added in v0.4.0

type MemberFailure struct {
	Kind    string // "member", "membermanager" or "condition" (automember)
	Type    string // the key FreeIPA reports: "user", "group", "host", "hbacsvc", ..., or the automember regex attribute
	Name    string
	Message string
}

MemberFailure is one member FreeIPA refused to add or remove.

type Message added in v0.2.0

type Message struct {
	Type    string          `json:"type"`
	Name    string          `json:"name"`
	Message string          `json:"message"`
	Code    int             `json:"code"`
	Data    json.RawMessage `json:"data"`
}

Message is a server warning attached to a FreeIPA result.

type Modification added in v0.7.0

type Modification struct {
	// contains filtered or unexported fields
}

Modification builds one *_mod call that changes single values with FreeIPA's setattr, addattr and delattr options. It is a builder: not safe for concurrent use.

func (*Modification) Add added in v0.7.0

func (m *Modification) Add(attr, value string) *Modification

Add appends value to the attribute's values.

func (*Modification) Del added in v0.7.0

func (m *Modification) Del(attr, value string) *Modification

Del removes value from the attribute's values.

func (*Modification) Run added in v0.7.0

func (m *Modification) Run(ctx context.Context) (*Response, error)

Run sends the call: setattr, addattr and delattr in call order within each kind, with all: true. A call that changes nothing returns ErrEmptyModlist as the server sent it.

func (*Modification) Set added in v0.7.0

func (m *Modification) Set(attr, value string) *Modification

Set replaces the attribute's values with value; Set(attr, "") clears it. Several Set calls for one attribute give it several values.

type OTPToken

type OTPToken struct {
	DN          string    `json:"dn"`
	UUID        string    `json:"ipatokenuniqueid"`
	Algorithm   string    `json:"ipatokenotpalgorithm"`
	Digits      int       `json:"ipatokenotpdigits"`
	Owner       string    `json:"ipatokenowner"`
	TimeStep    int       `json:"ipatokentotptimestep"`
	ClockOffest int       `json:"ipatokentotpclockoffset"`
	ManagedBy   string    `json:"managedby_user"`
	Enabled     bool      `json:"-"`
	Type        string    `json:"type"`
	URI         string    `json:"uri"`
	Description string    `json:"description"`
	Vendor      string    `json:"ipatokenvendor"`
	Model       string    `json:"ipatokenmodel"`
	Serial      string    `json:"ipatokenserial"`
	NotBefore   time.Time `json:"ipatokennotbefore"`
	NotAfter    time.Time `json:"ipatokennotafter"`
}

OTPToken encapsulates FreeIPA otptokens

var DefaultTOTPToken *OTPToken = &OTPToken{
	Type:      TokenTypeTOTP,
	Algorithm: AlgorithmSHA1,
	Digits:    6,
	TimeStep:  30,
}

DefaultTOTPToken holds the defaults AddOTPToken applies to zero fields.

Deprecated: use AddOTPToken(nil), or leave fields zero; the defaults apply field by field. Changing this variable while AddOTPToken runs is a data race.

func (*OTPToken) DisplayName

func (t *OTPToken) DisplayName() string

type Option added in v0.6.0

type Option func(*settings) error

Option configures a Client built by New.

func WithCACert added in v0.6.0

func WithCACert(pem []byte) Option

WithCACert trusts the PEM-encoded CA certificate(s) instead of /etc/ipa/ca.crt. It cannot be combined with WithHTTPClient.

func WithHTTPClient added in v0.6.0

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient makes the Client use hc. The caller owns its timeouts, proxy and transport; it cannot be combined with WithCACert.

Example

WithHTTPClient wraps the transport; compiled but not run. The caller owns the TLS settings of the client it passes: replace http.DefaultTransport with a transport that trusts the FreeIPA CA.

package main

import (
	"log"
	"net/http"
	"time"

	ipa "github.com/neverlless/goipa"
)

// timingTransport times each request. Any http.RoundTripper fits the same
// way, for example OpenTelemetry's otelhttp.NewTransport.
type timingTransport struct{ next http.RoundTripper }

func (t timingTransport) RoundTrip(r *http.Request) (*http.Response, error) {
	start := time.Now()
	res, err := t.next.RoundTrip(r)
	log.Printf("%s %s took %s", r.Method, r.URL.Path, time.Since(start))
	return res, err
}

func main() {
	hc := &http.Client{
		Timeout:   30 * time.Second,
		Transport: timingTransport{next: http.DefaultTransport},
	}
	c, err := ipa.New(
		ipa.WithHost("ipa.example.com"),
		ipa.WithRealm("EXAMPLE.COM"),
		ipa.WithHTTPClient(hc),
	)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.RemoteLogin("jesse", "secret"); err != nil {
		log.Fatal(err)
	}
}

func WithHost added in v0.6.0

func WithHost(host string) Option

WithHost sets the FreeIPA server, "ipa.example.com" or "ipa.example.com:8443".

func WithKrb5Config added in v0.6.0

func WithKrb5Config(path string) Option

WithKrb5Config reads the Kerberos configuration from path instead of DefaultKerbConf.

func WithKrb5ConfigData added in v0.6.0

func WithKrb5ConfigData(data []byte) Option

WithKrb5ConfigData uses krb5.conf text instead of DefaultKerbConf. include and includedir directives in it are resolved from the filesystem.

func WithPasswordRelogin added in v0.6.0

func WithPasswordRelogin() Option

WithPasswordRelogin keeps the password given to RemoteLogin in memory and logs in again once when FreeIPA answers 401 for an expired session. Off by default; needs sticky sessions. The user name and password stay in the Client, so a %+v dump of the struct shows them. A password FreeIPA rejects on re-login is forgotten, and so are both after ClearSession.

Example

With WithPasswordRelogin the client keeps the password in memory and logs in again when the session expires; compiled but not run.

package main

import (
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New(
		ipa.WithHost("ipa.example.com"),
		ipa.WithPasswordRelogin(),
	)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.RemoteLogin("jesse", "secret"); err != nil {
		log.Fatal(err)
	}
}

func WithRealm added in v0.6.0

func WithRealm(realm string) Option

WithRealm sets the Kerberos realm.

func WithTruncationErrors added in v1.1.0

func WithTruncationErrors() Option

WithTruncationErrors makes UserFind, GroupFind, HostFind, StageUserFind, SubIDFind, FetchOTPTokens, HBACRuleFind and SudoRuleFind (and their Context twins) return ErrTruncated together with the entries they got when the server cut the search short. Off by default, so a caller that treats any error as failure keeps getting its results.

func WithValidation added in v0.8.0

func WithValidation() Option

WithValidation checks every call against the command catalogue before sending it: an unknown command or option, or more arguments than the command takes, fails with ErrInvalidCall; a command or option newer than the server version from the last response fails with ErrNotSupported. Before the version is known nothing fails with ErrNotSupported, and a server newer than the newest catalogued release is not checked at all. Argument values and types are not checked. An option key that names a positional argument is accepted. The version gate follows the replica that answered last (see ErrNotSupported), so in a mixed 4.9/4.13 fleet behind a load balancer a call valid on 4.13 can get ErrNotSupported. Since values are upstream releases; distro backports are not known. Opt-in through New only: the old constructors never validate.

Example

WithValidation checks every call against the command catalogue before it is sent; compiled but not run.

package main

import (
	"errors"
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New(ipa.WithHost("ipa.example.com"), ipa.WithRealm("EXAMPLE.COM"), ipa.WithValidation())
	if err != nil {
		log.Fatal(err)
	}
	_, err = c.RPC("user_show", []string{"jesse"}, ipa.Options{"no_such_option": true})
	if errors.Is(err, ipa.ErrInvalidCall) {
		fmt.Println("rejected before sending:", err)
	}
}

type Options

type Options map[string]interface{}

FreeIPA api options map

type Param added in v0.8.0

type Param struct {
	Name     string // without the ?*+ suffix
	Type     string // API.txt class: "Str", "Flag", "Int", "DNParam", …
	Required bool   // the caller must send it
	Multi    bool   // takes a list of values
	Since    string
}

Param is a positional argument or an option of a Command. Type and the required/multi flags are those of the newest catalogued release.

type Permission added in v0.9.0

type Permission struct {
	// cn
	Name string
	// ipapermright
	Rights []string
	// type
	Type string
	// attrs
	Attrs []string
	// ipapermbindruletype
	BindType string
	// ipapermlocation
	Location string
	// ipapermtargetfilter
	Filters []string
	// targetgroup
	TargetGroup string
	// member_privilege
	Privileges []string
}

Permission is a FreeIPA permission, the unit of access control. Change attributes with Modify("permission_mod", …).

type Privilege added in v0.9.0

type Privilege struct {
	// cn, description
	Name, Description string
	// memberof_permission
	Permissions []string
	// member_role
	Roles []string
}

Privilege is a FreeIPA privilege: a named set of permissions. Change attributes with Modify("privilege_mod", …).

type PwPolicy added in v0.5.0

type PwPolicy struct {
	// cn: "global_policy" or the group the policy belongs to
	Name string
	// cospriority; group policies only. 0 from UserPwPolicy: FreeIPA does not
	// return it for the effective policy, use PwPolicyShow(Name).
	Priority int
	// krbmaxpwdlife (days on the wire), krbminpwdlife (hours on the wire)
	MaxLife, MinLife time.Duration
	// krbpwdhistorylength, krbpwdmindiffchars, krbpwdminlength, krbpwdmaxfailure
	HistoryLength, MinClasses, MinLength, MaxFailures int
	// krbpwdfailurecountinterval (seconds), krbpwdlockoutduration (seconds;
	// 0 = locked until an admin unlocks)
	FailureInterval, LockoutDuration time.Duration
	// ipapwdmaxrepeat, ipapwdmaxsequence
	MaxRepeat, MaxSequence int
	// ipapwddictcheck, ipapwdusercheck
	DictCheck, UserCheck bool
	// passwordgracelimit, FreeIPA 4.9.10+; -1 = no grace logins enforced
	GraceLimit int
	// ipapwddcredit, ipapwducredit, ipapwdlcredit, ipapwdocredit; FreeIPA 4.13+,
	// zero on older servers (they do not return the attributes)
	DigitCredit, UpperCredit, LowerCredit, OtherCredit int
}

PwPolicy is a FreeIPA password policy. Attributes the server does not return (older releases, unset values) are zero.

type ReplicaStatus added in v0.5.0

type ReplicaStatus struct {
	// Server is the master; only the host part when it could not be queried
	// (then Err is set).
	Server string
	// Err is the reason the master could not be queried, "" when it answered.
	Err string
	// FailedLogins is krbloginfailedcount.
	FailedLogins int
	// LastSuccess and LastFailure are krblastsuccessfulauth and
	// krblastfailedauth, read from FreeIPA's {"__datetime__": ...} form or an
	// RFC 3339 string; zero for "N/A".
	LastSuccess, LastFailure time.Time
	// Now is the master's clock.
	Now time.Time
}

ReplicaStatus is one IPA master's view of a user's Kerberos login state (user_status).

type Response

type Response struct {
	// Deprecated: never set in a *Response goipa returns; the FreeIPA error is
	// the returned error, a bare *IpaError.
	Error     *IpaError `json:"error"`
	ID        int       `json:"id"`
	Principal string    `json:"principal"`
	Version   string    `json:"version"`
	Result    *Result   `json:"result"`
}

Response returned from a FreeIPA JSON rpc call

ID is always 0.

type Result

type Result struct {
	Summary   string          `json:"summary"`
	Value     interface{}     `json:"value"`
	Data      json.RawMessage `json:"result"`
	Count     int             `json:"count"`
	Truncated bool            `json:"truncated"`
	Messages  []Message       `json:"messages"`
	Completed int             `json:"completed"`
	Failed    json.RawMessage `json:"failed"`
	// Raw is the whole FreeIPA result object, for shapes without a "result"
	// key such as hbactest.
	Raw json.RawMessage `json:"-"`
}

Result returned from a FreeIPA JSON rpc call

func Call added in v0.7.0

func Call[T any](ctx context.Context, c *Client, method string, args []string, opts Options) (T, *Result, error)

Call runs a FreeIPA command and decodes its "result" into T, or the whole result object when the command sends none (whoami, hbactest). T may be Entry, []Entry, a struct of your own or json.RawMessage. A FreeIPA failure is returned as a bare *IpaError.

Example

Call decodes any command's result; Entry reads FreeIPA's attribute encoding. Compiled but not run.

package main

import (
	"context"
	"fmt"
	"log"

	ipa "github.com/neverlless/goipa"
)

func main() {
	c, err := ipa.New()
	if err != nil {
		log.Fatal(err)
	}
	u, _, err := ipa.Call[ipa.Entry](context.Background(), c, "user_show",
		[]string{"jesse"}, ipa.Options{"all": true})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Str("uid"), u.Strs("mail"), u.Time("krbpasswordexpiration"))
}

func (*Result) UnmarshalJSON added in v0.2.0

func (r *Result) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes the result and keeps a copy of the raw object in Raw.

type Role added in v0.9.0

type Role struct {
	// cn, description
	Name, Description string
	// member_user, member_group, member_host, member_hostgroup, member_service
	Users, Groups, Hosts, HostGroups, Services []string
	// memberof_privilege
	Privileges []string
}

Role is a FreeIPA role: the privileges it grants and who holds it. Change attributes with Modify("role_mod", …).

type SSHAuthorizedKey

type SSHAuthorizedKey struct {
	Comment     string
	Options     []string
	PublicKey   ssh.PublicKey
	Fingerprint string
}

SSH Public Key

func NewSSHAuthorizedKey

func NewSSHAuthorizedKey(in string) (*SSHAuthorizedKey, error)

func (*SSHAuthorizedKey) MarshalJSON

func (k *SSHAuthorizedKey) MarshalJSON() ([]byte, error)

func (*SSHAuthorizedKey) String

func (k *SSHAuthorizedKey) String() string

type Service added in v0.9.0

type Service struct {
	Principal      string   // krbcanonicalname
	Aliases        []string // krbprincipalname
	ManagedBy      []string // managedby_host
	HasKeytab      bool     // has_keytab
	Certificates   [][]byte // usercertificate (DER)
	AuthIndicators []string // krbprincipalauthind
	// ipakrbokasdelegate, ipakrboktoauthasdelegate, ipakrbrequirespreauth
	OKAsDelegate, OKToAuthAsDelegate, RequiresPreAuth bool
	// ipaallowedtoperform_read_keys_{user,group,host,hostgroup} and
	// ipaallowedtoperform_write_keys_*
	KeytabRetrieve, KeytabCreate KeytabAccess
}

Service is a FreeIPA Kerberos service principal. Attribute changes go through Modify with `service_mod`.

type SubID added in v0.5.0

type SubID struct {
	// ipauniqueid, ipaowner, description
	ID, Owner, Description string
	// ipasubuidnumber, ipasubuidcount
	UIDStart, UIDCount int64
	// ipasubgidnumber, ipasubgidcount
	GIDStart, GIDCount int64
}

SubID is a subordinate UID/GID range of a user.

type SudoRule added in v0.5.0

type SudoRule struct {
	// cn, description
	Name, Description string
	// ipaenabledflag
	Enabled bool
	// usercategory, hostcategory, cmdcategory: "all" or ""
	UserCategory, HostCategory, CmdCategory string
	// ipasudorunasusercategory, ipasudorunasgroupcategory
	RunAsUserCategory, RunAsGroupCategory string
	// memberuser_user, memberuser_group, memberhost_host, memberhost_hostgroup
	Users, Groups, Hosts, HostGroups []string
	// memberallowcmd_sudocmd, memberallowcmd_sudocmdgroup,
	// memberdenycmd_sudocmd, memberdenycmd_sudocmdgroup
	AllowCommands, AllowCommandGroups, DenyCommands, DenyCommandGroups []string
	// ipasudorunas_user, ipasudorunasgroup_group
	RunAsUsers, RunAsGroups []string
	// ipasudorunas_group: groups whose members the commands may run as
	RunAsUserGroups []string
	// ipasudoopt
	Options []string
	// sudoorder
	Order int
}

SudoRule is a sudo rule. Its description, order and categories change through Modify("sudorule_mod", name). FreeIPA keeps users, groups, hosts and run-as users and groups it does not know as external members (externaluser, externalhost, ipasudorunasextuser, ipasudorunasextusergroup, ipasudorunasextgroup), which SudoRule does not carry; adding such a name succeeds without a *MemberError.

type User

type User struct {
	UUID             string              `json:"ipauniqueid"`
	DN               string              `json:"dn"`
	First            string              `json:"givenname"`
	Last             string              `json:"sn"`
	DisplayName      string              `json:"displayname"`
	Principal        string              `json:"krbprincipalname"`
	Username         string              `json:"uid"`
	Uid              string              `json:"uidnumber"`
	Gid              string              `json:"gidnumber"`
	Groups           []string            `json:"memberof_group"`
	SSHAuthKeys      []*SSHAuthorizedKey `json:"ipasshpubkey"`
	AuthTypes        []string            `json:"ipauserauthtype"`
	HasKeytab        bool                `json:"has_keytab"`
	HasPassword      bool                `json:"has_password"`
	Locked           bool                `json:"nsaccountlock"`
	Preserved        bool                `json:"preserved"`
	HomeDir          string              `json:"homedirectory"`
	Email            string              `json:"mail"`
	TelephoneNumber  string              `json:"telephonenumber"`
	Mobile           string              `json:"mobile"`
	Shell            string              `json:"loginshell"`
	Category         string              `json:"userclass"`
	SudoRules        []string            `json:"memberofindirect_sudorule"`
	HbacRules        []string            `json:"memberofindirect_hbacrule"`
	LastPasswdChange time.Time           `json:"krblastpwdchange"`
	PasswdExpire     time.Time           `json:"krbpasswordexpiration"`
	PrincipalExpire  time.Time           `json:"krbprincipalexpiration"`
	LastLoginSuccess time.Time           `json:"krblastsuccessfulauth"`
	LastLoginFail    time.Time           `json:"krblastfailedauth"`
	RandomPassword   string              `json:"randompassword"`

	// Emails holds every mail value; Email is the first. UserMod and UserAdd
	// send Email first, then Emails[1:] (see ToOptions), so Emails[0] is
	// ignored on write. To set the whole list, set Email = list[0] and
	// Emails = list.
	Emails []string `json:"emails"`
	// IndirectGroups: nested groups; filled by UserShow only, UserFind puts
	// nested groups in Groups (FreeIPA).
	IndirectGroups []string `json:"memberofindirect_group"`
	// Street, City, State, PostalCode and PreferredLanguage are returned only
	// with all, which UserShow and UserFind send.
	Street            string `json:"street"`
	City              string `json:"l"`
	State             string `json:"st"`
	PostalCode        string `json:"postalcode"`
	PreferredLanguage string `json:"preferredlanguage"`
	Title             string `json:"title"`
	OrgUnit           string `json:"ou"`
	// Passkeys: FreeIPA 4.11+, format passkey:<id>,<key>[,<userid>].
	Passkeys []string `json:"ipapasskey"`
}

User encapsulates user data returned from ipa user commands

func (*User) AddSSHAuthorizedKey

func (u *User) AddSSHAuthorizedKey(key *SSHAuthorizedKey)

Add ssh authorized key

func (*User) FormatSSHAuthorizedKeys

func (u *User) FormatSSHAuthorizedKeys() []string

Format ssh authorized keys

func (*User) HasGroup

func (u *User) HasGroup(group string) bool

Returns true if the User is in group

func (*User) OTPOnly

func (u *User) OTPOnly() bool

Returns true if OTP is the only authentication type enabled

func (*User) RemoveSSHAuthorizedKey

func (u *User) RemoveSSHAuthorizedKey(fingerprint string)

Removes ssh authorized key

func (*User) ToOptions

func (u *User) ToOptions() Options

Directories

Path Synopsis
internal
gencatalogue command
Command gencatalogue writes the FreeIPA command catalogue from the API.txt of every FreeIPA release since 4.9.0.
Command gencatalogue writes the FreeIPA command catalogue from the API.txt of every FreeIPA release since 4.9.0.
Package ipatest provides a fake FreeIPA server for tests of code that uses goipa, so they run without a real IPA.
Package ipatest provides a fake FreeIPA server for tests of code that uses goipa, so they run without a real IPA.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL