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, or NewDefaultClient on a host enrolled in FreeIPA. A *Client is safe for concurrent use.
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, NewDefaultClientWithSession 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.
A FreeIPA error is returned as a bare *IpaError: match it with errors.Is against ErrNotFound and the other sentinels, or with a type assertion.
Every method that talks to the server has a ...Context twin that bounds the request with a context, except the Kerberos logins (Login, LoginWithKeytab, LoginFromCCache and their Data variants; gokrb5 is not cancellable). RPC calls any command goipa does not wrap.
Any command ¶
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.
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 := ipa.NewClient("ipa.example.com", "EXAMPLE.COM")
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)
}
Output:
Index ¶
- Constants
- Variables
- func ParseDateTime(str string) time.Time
- type BatchCall
- type BatchResult
- type Client
- func (c *Client) AddOTPToken(token *OTPToken) (*OTPToken, error)
- func (c *Client) AddOTPTokenContext(ctx context.Context, token *OTPToken) (*OTPToken, error)
- func (c *Client) Batch(ctx context.Context, calls ...BatchCall) ([]BatchResult, error)
- func (c *Client) ChangePassword(username, oldPasswd, newPasswd, otpcode string) error
- func (c *Client) ChangePasswordContext(ctx context.Context, username, oldPasswd, newPasswd, otpcode string) error
- func (c *Client) ClearSession()
- func (c *Client) DisableOTPToken(tokenUUID string) error
- func (c *Client) DisableOTPTokenContext(ctx context.Context, tokenUUID string) error
- func (c *Client) EnableOTPToken(tokenUUID string) error
- func (c *Client) EnableOTPTokenContext(ctx context.Context, tokenUUID string) error
- func (c *Client) FetchOTPTokens(owner string) ([]*OTPToken, error)
- func (c *Client) FetchOTPTokensContext(ctx context.Context, owner string) ([]*OTPToken, error)
- func (c *Client) GroupAdd(group *Group) (*Group, error)
- func (c *Client) GroupAddContext(ctx context.Context, group *Group) (*Group, error)
- func (c *Client) GroupAddMember(group string, users, groups []string) (*Group, error)
- func (c *Client) GroupAddMemberContext(ctx context.Context, group string, users, groups []string) (*Group, error)
- func (c *Client) GroupAddMemberManager(group string, users, groups []string) (*Group, error)
- func (c *Client) GroupAddMemberManagerContext(ctx context.Context, group string, users, groups []string) (*Group, error)
- func (c *Client) GroupDelete(names ...string) error
- func (c *Client) GroupDeleteContext(ctx context.Context, names ...string) error
- func (c *Client) GroupFind(options Options) ([]*Group, error)
- func (c *Client) GroupFindContext(ctx context.Context, options Options) ([]*Group, error)
- func (c *Client) GroupMod(group *Group) (*Group, error)
- func (c *Client) GroupModContext(ctx context.Context, group *Group) (*Group, error)
- func (c *Client) GroupRemoveMember(group string, users, groups []string) (*Group, error)
- func (c *Client) GroupRemoveMemberContext(ctx context.Context, group string, users, groups []string) (*Group, error)
- func (c *Client) GroupRemoveMemberManager(group string, users, groups []string) (*Group, error)
- func (c *Client) GroupRemoveMemberManagerContext(ctx context.Context, group string, users, groups []string) (*Group, error)
- func (c *Client) GroupShow(name string) (*Group, error)
- func (c *Client) GroupShowContext(ctx context.Context, name string) (*Group, error)
- func (c *Client) HBACRuleFind(options Options) ([]*HBACRule, error)
- func (c *Client) HBACRuleFindContext(ctx context.Context, options Options) ([]*HBACRule, error)
- func (c *Client) HBACTest(user, host, service string, rules ...string) (*HBACTestResult, error)
- func (c *Client) HBACTestContext(ctx context.Context, user, host, service string, rules ...string) (*HBACTestResult, error)
- func (c *Client) Host() string
- func (c *Client) HostFind(options Options) ([]*Host, error)
- func (c *Client) HostFindContext(ctx context.Context, options Options) ([]*Host, error)
- func (c *Client) HostShow(fqdn string) (*Host, error)
- func (c *Client) HostShowContext(ctx context.Context, fqdn string) (*Host, error)
- func (c *Client) Login(username, password string) error
- func (c *Client) LoginFromCCache(cpath string) error
- func (c *Client) LoginFromCCacheData(ccache []byte) error
- func (c *Client) LoginWithKeytab(ktab, username string) error
- func (c *Client) LoginWithKeytabData(ktab []byte, username string) error
- func (c *Client) Modify(command string, keys ...string) *Modification
- func (c *Client) Ping() (*Response, error)
- func (c *Client) PingContext(ctx context.Context) (*Response, error)
- func (c *Client) PwPolicyShow(group string) (*PwPolicy, error)
- func (c *Client) PwPolicyShowContext(ctx context.Context, group string) (*PwPolicy, error)
- func (c *Client) RPC(method string, args []string, options Options) (*Response, error)
- func (c *Client) RPCContext(ctx context.Context, method string, args []string, options Options) (*Response, error)
- func (c *Client) Realm() string
- func (c *Client) RemoteLogin(uid, passwd string) error
- func (c *Client) RemoteLoginContext(ctx context.Context, uid, passwd string) error
- func (c *Client) RemoveOTPToken(tokenUUID string) error
- func (c *Client) RemoveOTPTokenContext(ctx context.Context, tokenUUID string) error
- func (c *Client) ResetPassword(username string) (string, error)
- func (c *Client) ResetPasswordContext(ctx context.Context, username string) (string, error)
- func (c *Client) ServerVersion() string
- func (c *Client) SessionID() string
- func (c *Client) SetAuthTypes(username string, types []string) error
- func (c *Client) SetAuthTypesContext(ctx context.Context, username string, types []string) error
- func (c *Client) SetPassword(username, oldPasswd, newPasswd, otpcode string) error
- func (c *Client) SetPasswordContext(ctx context.Context, username, oldPasswd, newPasswd, otpcode string) error
- func (c *Client) SetSessionID(sessionID string)
- func (c *Client) StageUserActivate(username string) (*User, error)
- func (c *Client) StageUserActivateContext(ctx context.Context, username string) (*User, error)
- func (c *Client) StageUserAdd(user *User) (*User, error)
- func (c *Client) StageUserAddContext(ctx context.Context, user *User) (*User, error)
- func (c *Client) StageUserDelete(usernames ...string) error
- func (c *Client) StageUserDeleteContext(ctx context.Context, usernames ...string) error
- func (c *Client) StageUserFind(options Options) ([]*User, error)
- func (c *Client) StageUserFindContext(ctx context.Context, options Options) ([]*User, error)
- func (c *Client) StageUserMod(user *User) (*User, error)
- func (c *Client) StageUserModContext(ctx context.Context, user *User) (*User, error)
- func (c *Client) StageUserShow(username string) (*User, error)
- func (c *Client) StageUserShowContext(ctx context.Context, username string) (*User, error)
- func (c *Client) StickySession(enable bool)
- func (c *Client) SubIDFind(options Options) ([]*SubID, error)
- func (c *Client) SubIDFindContext(ctx context.Context, options Options) ([]*SubID, error)
- func (c *Client) SubIDGenerate(owner string) (*SubID, error)
- func (c *Client) SubIDGenerateContext(ctx context.Context, owner string) (*SubID, error)
- func (c *Client) SudoRuleFind(options Options) ([]*SudoRule, error)
- func (c *Client) SudoRuleFindContext(ctx context.Context, options Options) ([]*SudoRule, error)
- func (c *Client) SyncOTPToken(username, password, firstCode, secondCode, tokenID string) error
- func (c *Client) SyncOTPTokenContext(ctx context.Context, username, password, firstCode, secondCode, tokenID string) error
- func (c *Client) UserAdd(user *User, random bool) (*User, error)
- func (c *Client) UserAddContext(ctx context.Context, user *User, random bool) (*User, error)
- func (c *Client) UserAddPasskey(username, mapping string) error
- func (c *Client) UserAddPasskeyContext(ctx context.Context, username, mapping string) error
- func (c *Client) UserAddWithPassword(user *User, password string) (*User, error)
- func (c *Client) UserAddWithPasswordContext(ctx context.Context, user *User, password string) (*User, error)
- func (c *Client) UserDelete(preserve, stopOnError bool, usernames ...string) error
- func (c *Client) UserDeleteContext(ctx context.Context, preserve, stopOnError bool, usernames ...string) error
- func (c *Client) UserDisable(username string) error
- func (c *Client) UserDisableContext(ctx context.Context, username string) error
- func (c *Client) UserEnable(username string) error
- func (c *Client) UserEnableContext(ctx context.Context, username string) error
- func (c *Client) UserFind(options Options) ([]*User, error)
- func (c *Client) UserFindContext(ctx context.Context, options Options) ([]*User, error)
- func (c *Client) UserMod(user *User) (*User, error)
- func (c *Client) UserModContext(ctx context.Context, user *User) (*User, error)
- func (c *Client) UserPwPolicy(username string) (*PwPolicy, error)
- func (c *Client) UserPwPolicyContext(ctx context.Context, username string) (*PwPolicy, error)
- func (c *Client) UserRemovePasskey(username, mapping string) error
- func (c *Client) UserRemovePasskeyContext(ctx context.Context, username, mapping string) error
- func (c *Client) UserShow(username string) (*User, error)
- func (c *Client) UserShowContext(ctx context.Context, username string) (*User, error)
- func (c *Client) UserStatus(username string) ([]*ReplicaStatus, error)
- func (c *Client) UserStatusContext(ctx context.Context, username string) ([]*ReplicaStatus, error)
- func (c *Client) UserUnlock(username string) error
- func (c *Client) UserUnlockContext(ctx context.Context, username string) error
- func (c *Client) WhoAmI() (*Identity, error)
- func (c *Client) WhoAmIContext(ctx context.Context) (*Identity, error)
- type Entry
- func (e Entry) Bool(attr string) bool
- func (e Entry) Bytes(attr string) []byte
- func (e Entry) DN(attr string) string
- func (e Entry) Has(attr string) bool
- func (e Entry) Int(attr string) (int64, bool)
- func (e Entry) MarshalJSON() ([]byte, error)
- func (e Entry) Raw() json.RawMessage
- func (e Entry) Str(attr string) string
- func (e Entry) Strs(attr string) []string
- func (e Entry) Time(attr string) time.Time
- func (e *Entry) UnmarshalJSON(b []byte) error
- type Group
- type HBACRule
- type HBACTestResult
- type HTTPError
- type Host
- type Identity
- type IpaError
- type MemberError
- type MemberFailure
- type Message
- type Modification
- type OTPToken
- type Option
- type Options
- type PwPolicy
- type ReplicaStatus
- type Response
- type Result
- type SSHAuthorizedKey
- type SubID
- type SudoRule
- type User
Examples ¶
Constants ¶
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).
const ( DefaultKerbConf = "/etc/krb5.conf" IpaClientVersion = "2.237" IpaDatetimeFormat = "20060102150405Z" )
const ( AlgorithmSHA1 = "sha1" AlgorithmSHA256 = "sha256" AlgorithmSHA384 = "sha384" AlgorithmSHA512 = "sha512" )
OTP Token hash Algorithms supported by FreeIPA
const ( TokenTypeTOTP = "totp" TokenTypeHOTP = "hotp" )
OTP Token types supported by FreeIPA
Variables ¶
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.
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 = errors.New("unauthorized") // ErrUserExists is returned when user account already exists. UserAdd // returns it for FreeIPA's DuplicateEntry (4002). ErrUserExists = errors.New("user exists") )
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.
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 ¶
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"]}'
Types ¶
type BatchResult ¶ added in v0.7.0
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 Client ¶
type Client struct {
// contains filtered or unexported fields
}
FreeIPA Client
Methods with a Context suffix bound the HTTP request with the given context. 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
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)
}
}
Output:
func NewClientCustomHttp ¶
New IPA Client with host, realm and custom http client
func NewDefaultClient ¶
func NewDefaultClient() *Client
New default IPA Client using host and realm from /etc/ipa/default.conf, read on first use
func NewDefaultClientWithSession ¶
New default IPA Client with existing sessionID using host and realm from /etc/ipa/default.conf, read on first use
func (*Client) AddOTPToken ¶
Add OTP token. Returns new OTPToken
func (*Client) AddOTPTokenContext ¶ added in v0.2.0
AddOTPTokenContext is like AddOTPToken but bounds the request with ctx.
func (*Client) Batch ¶ added in v0.7.0
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 := ipa.NewDefaultClient()
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)
}
}
}
Output:
func (*Client) ChangePassword ¶
Change user password. This will run the passwd ipa command. Optionally provide an OTP if required
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) DisableOTPToken ¶
Disable OTP token.
func (*Client) DisableOTPTokenContext ¶ added in v0.2.0
DisableOTPTokenContext is like DisableOTPToken but bounds the request with ctx.
func (*Client) EnableOTPToken ¶
Enable OTP token.
func (*Client) EnableOTPTokenContext ¶ added in v0.2.0
EnableOTPTokenContext is like EnableOTPToken but bounds the request with ctx.
func (*Client) FetchOTPTokens ¶
Fetch OTP tokens by owner.
func (*Client) FetchOTPTokensContext ¶ added in v0.2.0
FetchOTPTokensContext is like FetchOTPTokens but bounds the request with ctx.
func (*Client) GroupAdd ¶ added in v0.4.0
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
GroupAddContext is like GroupAdd but bounds the request with ctx.
func (*Client) GroupAddMember ¶ added in v0.4.0
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
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
GroupDelete deletes groups with `group_del`; it requires the Group Administrators privilege (System: Remove Groups).
func (*Client) GroupDeleteContext ¶ added in v0.4.0
GroupDeleteContext is like GroupDelete but bounds the request with ctx.
func (*Client) GroupFind ¶ added in v0.4.0
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).
func (*Client) GroupFindContext ¶ added in v0.4.0
GroupFindContext is like GroupFind but bounds the request with ctx.
func (*Client) GroupMod ¶ added in v0.4.0
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
GroupModContext is like GroupMod but bounds the request with ctx.
func (*Client) GroupRemoveMember ¶ added in v0.4.0
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
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
GroupShow fetches a group with `group_show`. Any authenticated user may read groups (System: Read Groups).
func (*Client) GroupShowContext ¶ added in v0.4.0
GroupShowContext is like GroupShow but bounds the request with ctx.
func (*Client) HBACRuleFind ¶ added in v0.5.0
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.
func (*Client) HBACRuleFindContext ¶ added in v0.5.0
HBACRuleFindContext is like HBACRuleFind 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) HostFind ¶ added in v0.4.0
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.
func (*Client) HostFindContext ¶ added in v0.4.0
HostFindContext is like HostFind but bounds the request with ctx.
func (*Client) HostShow ¶ added in v0.4.0
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
HostShowContext is like HostShow but bounds the request with ctx.
func (*Client) Login ¶
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 := ipa.NewClient("ipa.example.com", "EXAMPLE.COM")
if err := c.Login("jesse", "secret"); err != nil {
log.Fatal(err)
}
}
Output:
func (*Client) LoginFromCCache ¶
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 := ipa.NewDefaultClient()
if err := c.LoginFromCCache("/tmp/krb5cc_1000"); err != nil {
log.Fatal(err)
}
}
Output:
func (*Client) LoginFromCCacheData ¶ added in v0.6.0
LoginFromCCacheData is like LoginFromCCache but takes the credentials cache contents.
func (*Client) LoginWithKeytab ¶
Login to FreeIPA using local kerberos login with keytab and username
func (*Client) LoginWithKeytabData ¶ added in v0.6.0
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)
}
}
Output:
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 := ipa.NewDefaultClient()
_, err := c.Modify("user_mod", "jesse").
Set("title", "Engineer").
Add("mail", "jesse@example.com").
Run(context.Background())
if err != nil {
log.Fatal(err)
}
}
Output:
func (*Client) PingContext ¶ added in v0.2.0
PingContext is like Ping but bounds the request with ctx.
func (*Client) PwPolicyShow ¶ added in v0.5.0
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
PwPolicyShowContext is like PwPolicyShow but bounds the request with ctx.
func (*Client) RPC ¶ added in v0.2.0
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) RemoteLogin ¶
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 := ipa.NewDefaultClient()
if err := c.RemoteLogin("jesse", "secret"); err != nil {
log.Fatal(err)
}
sid := c.SessionID()
later := ipa.NewDefaultClientWithSession(sid)
u, err := later.UserShow("jesse")
if err != nil {
log.Fatal(err)
}
fmt.Println(u.Username)
}
Output:
func (*Client) RemoteLoginContext ¶ added in v0.2.0
RemoteLoginContext is like RemoteLogin but bounds the request with ctx.
func (*Client) RemoveOTPToken ¶
Remove OTP token
func (*Client) RemoveOTPTokenContext ¶ added in v0.2.0
RemoveOTPTokenContext is like RemoveOTPToken but bounds the request with ctx.
func (*Client) ResetPassword ¶
Reset user password and return new random password
func (*Client) ResetPasswordContext ¶ added in v0.2.0
ResetPasswordContext is like ResetPassword but bounds the request with ctx.
func (*Client) ServerVersion ¶ added in v0.7.0
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) SetAuthTypes ¶
Update user authentication types.
func (*Client) SetAuthTypesContext ¶ added in v0.2.0
SetAuthTypesContext is like SetAuthTypes but bounds the request with ctx.
func (*Client) SetPassword ¶
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.
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
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
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
StageUserActivateContext is like StageUserActivate but bounds the request with ctx.
func (*Client) StageUserAdd ¶ added in v0.5.0
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
StageUserAddContext is like StageUserAdd but bounds the request with ctx.
func (*Client) StageUserDelete ¶ added in v0.5.0
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
StageUserDeleteContext is like StageUserDelete but bounds the request with ctx.
func (*Client) StageUserFind ¶ added in v0.5.0
StageUserFind finds stage users with `stageuser_find`; options are passed through (e.g. `uid`, `sizelimit`). It requires the Stage User Administrators privilege.
func (*Client) StageUserFindContext ¶ added in v0.5.0
StageUserFindContext is like StageUserFind but bounds the request with ctx.
func (*Client) StageUserMod ¶ added in v0.5.0
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
StageUserModContext is like StageUserMod but bounds the request with ctx.
func (*Client) StageUserShow ¶ added in v0.5.0
StageUserShow fetches a stage user with `stageuser_show`. It requires the Stage User Administrators privilege.
func (*Client) StageUserShowContext ¶ added in v0.5.0
StageUserShowContext is like StageUserShow but bounds the request with ctx.
func (*Client) SubIDFind ¶ added in v0.5.0
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.
func (*Client) SubIDFindContext ¶ added in v0.5.0
SubIDFindContext is like SubIDFind but bounds the request with ctx.
func (*Client) SubIDGenerate ¶ added in v0.5.0
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
SubIDGenerateContext is like SubIDGenerate but bounds the request with ctx.
func (*Client) SudoRuleFind ¶ added in v0.5.0
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.
func (*Client) SudoRuleFindContext ¶ added in v0.5.0
SudoRuleFindContext is like SudoRuleFind but bounds the request with ctx.
func (*Client) SyncOTPToken ¶ added in v0.5.0
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 ¶
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
UserAddContext is like UserAdd but bounds the request with ctx.
func (*Client) UserAddPasskey ¶ added in v0.5.0
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
UserAddPasskeyContext is like UserAddPasskey but bounds the request with ctx.
func (*Client) UserAddWithPassword ¶
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 ¶
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
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 ¶
Disable User Account
func (*Client) UserDisableContext ¶ added in v0.2.0
UserDisableContext is like UserDisable but bounds the request with ctx.
func (*Client) UserEnableContext ¶ added in v0.2.0
UserEnableContext is like UserEnable but bounds the request with ctx.
func (*Client) UserFindContext ¶ added in v0.2.0
UserFindContext is like UserFind but bounds the request with ctx.
func (*Client) UserMod ¶
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
UserModContext is like UserMod but bounds the request with ctx.
func (*Client) UserPwPolicy ¶ added in v0.5.0
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
UserPwPolicyContext is like UserPwPolicy but bounds the request with ctx.
func (*Client) UserRemovePasskey ¶ added in v0.5.0
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
UserRemovePasskeyContext is like UserRemovePasskey but bounds the request with ctx.
func (*Client) UserShowContext ¶ added in v0.2.0
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
UserStatusContext is like UserStatus but bounds the request with ctx.
func (*Client) UserUnlock ¶ added in v0.5.0
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
UserUnlockContext is like UserUnlock but bounds the request with ctx.
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 := ipa.NewDefaultClient()
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"))
}
}
Output:
func (Entry) Int ¶ added in v0.7.0
Int parses a number or numeric string; ok is false when absent or not an integer.
func (Entry) MarshalJSON ¶ added in v0.7.0
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) Strs ¶ added in v0.7.0
Strs returns all values of the attribute; a scalar is one element. It is nil when the attribute is absent or null.
func (Entry) Time ¶ added in v0.7.0
Time reads a {"__datetime__": ...} hint or an RFC 3339 string; the zero time otherwise.
func (*Entry) UnmarshalJSON ¶ added in v0.7.0
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.
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
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.
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
}
Host is a FreeIPA host.
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) MarshalJSON ¶ added in v0.3.0
MarshalJSON writes FreeIPA's error shape; an empty or non-JSON Data becomes {}.
func (*IpaError) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON keeps Data as raw JSON text; Message and Code still match the "message" and "code" keys case-insensitively.
type MemberError ¶ added in v0.4.0
type MemberError struct {
Failures []MemberFailure
}
MemberError reports the members a group 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" or "membermanager"
Type string // "user" or "group"
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, }
func (*OTPToken) DisplayName ¶
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
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
WithHTTPClient makes the Client use hc. The caller owns its timeouts, proxy and transport; it cannot be combined with WithCACert.
func WithHost ¶ added in v0.6.0
WithHost sets the FreeIPA server, "ipa.example.com" or "ipa.example.com:8443".
func WithKrb5Config ¶ added in v0.6.0
WithKrb5Config reads the Kerberos configuration from path instead of DefaultKerbConf.
func WithKrb5ConfigData ¶ added in v0.6.0
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)
}
}
Output:
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 {
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
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 := ipa.NewDefaultClient()
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"))
}
Output:
func (*Result) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON decodes the result and keeps a copy of the raw object in Raw.
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 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
// ipasudoopt
Options []string
// sudoorder
Order int
}
SudoRule is a sudo rule.
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 ¶
Format ssh authorized keys
func (*User) RemoveSSHAuthorizedKey ¶
Removes ssh authorized key