blob: 62acab7a1547836c079102faafb9f63b107e66c8 [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001// Package credentials provides credentials management for Kerberos 5 authentication.
2package credentials
3
4import (
5 "time"
6
7 "github.com/hashicorp/go-uuid"
8 "gopkg.in/jcmturner/gokrb5.v7/iana/nametype"
9 "gopkg.in/jcmturner/gokrb5.v7/keytab"
10 "gopkg.in/jcmturner/gokrb5.v7/types"
11)
12
13const (
14 // AttributeKeyADCredentials assigned number for AD credentials.
15 AttributeKeyADCredentials = "gokrb5AttributeKeyADCredentials"
16)
17
18// Credentials struct for a user.
19// Contains either a keytab, password or both.
20// Keytabs are used over passwords if both are defined.
21type Credentials struct {
22 username string
23 displayName string
24 realm string
25 cname types.PrincipalName
26 keytab *keytab.Keytab
27 password string
28 attributes map[string]interface{}
29 validUntil time.Time
30
31 authenticated bool
32 human bool
33 authTime time.Time
34 groupMembership map[string]bool
35 sessionID string
36}
37
38// ADCredentials contains information obtained from the PAC.
39type ADCredentials struct {
40 EffectiveName string
41 FullName string
42 UserID int
43 PrimaryGroupID int
44 LogOnTime time.Time
45 LogOffTime time.Time
46 PasswordLastSet time.Time
47 GroupMembershipSIDs []string
48 LogonDomainName string
49 LogonDomainID string
50 LogonServer string
51}
52
53// New creates a new Credentials instance.
54func New(username string, realm string) *Credentials {
55 uid, err := uuid.GenerateUUID()
56 if err != nil {
57 uid = "00unique-sess-ions-uuid-unavailable0"
58 }
59 return &Credentials{
60 username: username,
61 displayName: username,
62 realm: realm,
63 cname: types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, username),
64 keytab: keytab.New(),
65 attributes: make(map[string]interface{}),
66 groupMembership: make(map[string]bool),
67 sessionID: uid,
68 human: true,
69 }
70}
71
72// NewFromPrincipalName creates a new Credentials instance with the user details provides as a PrincipalName type.
73func NewFromPrincipalName(cname types.PrincipalName, realm string) *Credentials {
74 uid, err := uuid.GenerateUUID()
75 if err != nil {
76 uid = "00unique-sess-ions-uuid-unavailable0"
77 }
78 return &Credentials{
79 username: cname.PrincipalNameString(),
80 displayName: cname.PrincipalNameString(),
81 realm: realm,
82 cname: cname,
83 keytab: keytab.New(),
84 attributes: make(map[string]interface{}),
85 groupMembership: make(map[string]bool),
86 sessionID: uid,
87 human: true,
88 }
89}
90
91// WithKeytab sets the Keytab in the Credentials struct.
92func (c *Credentials) WithKeytab(kt *keytab.Keytab) *Credentials {
93 c.keytab = kt
94 c.password = ""
95 return c
96}
97
98// Keytab returns the credential's Keytab.
99func (c *Credentials) Keytab() *keytab.Keytab {
100 return c.keytab
101}
102
103// HasKeytab queries if the Credentials has a keytab defined.
104func (c *Credentials) HasKeytab() bool {
105 if c.keytab != nil && len(c.keytab.Entries) > 0 {
106 return true
107 }
108 return false
109}
110
111// WithPassword sets the password in the Credentials struct.
112func (c *Credentials) WithPassword(password string) *Credentials {
113 c.password = password
114 c.keytab = keytab.New() // clear any keytab
115 return c
116}
117
118// Password returns the credential's password.
119func (c *Credentials) Password() string {
120 return c.password
121}
122
123// HasPassword queries if the Credentials has a password defined.
124func (c *Credentials) HasPassword() bool {
125 if c.password != "" {
126 return true
127 }
128 return false
129}
130
131// SetValidUntil sets the expiry time of the credentials
132func (c *Credentials) SetValidUntil(t time.Time) {
133 c.validUntil = t
134}
135
136// SetADCredentials adds ADCredentials attributes to the credentials
137func (c *Credentials) SetADCredentials(a ADCredentials) {
138 c.SetAttribute(AttributeKeyADCredentials, a)
139 if a.FullName != "" {
140 c.SetDisplayName(a.FullName)
141 }
142 if a.EffectiveName != "" {
143 c.SetUserName(a.EffectiveName)
144 }
145 for i := range a.GroupMembershipSIDs {
146 c.AddAuthzAttribute(a.GroupMembershipSIDs[i])
147 }
148}
149
150// Methods to implement goidentity.Identity interface
151
152// UserName returns the credential's username.
153func (c *Credentials) UserName() string {
154 return c.username
155}
156
157// SetUserName sets the username value on the credential.
158func (c *Credentials) SetUserName(s string) {
159 c.username = s
160}
161
162// CName returns the credential's client principal name.
163func (c *Credentials) CName() types.PrincipalName {
164 return c.cname
165}
166
167// SetCName sets the client principal name on the credential.
168func (c *Credentials) SetCName(pn types.PrincipalName) {
169 c.cname = pn
170}
171
172// Domain returns the credential's domain.
173func (c *Credentials) Domain() string {
174 return c.realm
175}
176
177// SetDomain sets the domain value on the credential.
178func (c *Credentials) SetDomain(s string) {
179 c.realm = s
180}
181
182// Realm returns the credential's realm. Same as the domain.
183func (c *Credentials) Realm() string {
184 return c.Domain()
185}
186
187// SetRealm sets the realm value on the credential. Same as the domain
188func (c *Credentials) SetRealm(s string) {
189 c.SetDomain(s)
190}
191
192// DisplayName returns the credential's display name.
193func (c *Credentials) DisplayName() string {
194 return c.displayName
195}
196
197// SetDisplayName sets the display name value on the credential.
198func (c *Credentials) SetDisplayName(s string) {
199 c.displayName = s
200}
201
202// Human returns if the credential represents a human or not.
203func (c *Credentials) Human() bool {
204 return c.human
205}
206
207// SetHuman sets the credential as human.
208func (c *Credentials) SetHuman(b bool) {
209 c.human = b
210}
211
212// AuthTime returns the time the credential was authenticated.
213func (c *Credentials) AuthTime() time.Time {
214 return c.authTime
215}
216
217// SetAuthTime sets the time the credential was authenticated.
218func (c *Credentials) SetAuthTime(t time.Time) {
219 c.authTime = t
220}
221
222// AuthzAttributes returns the credentials authorizing attributes.
223func (c *Credentials) AuthzAttributes() []string {
224 s := make([]string, len(c.groupMembership))
225 i := 0
226 for a := range c.groupMembership {
227 s[i] = a
228 i++
229 }
230 return s
231}
232
233// Authenticated indicates if the credential has been successfully authenticated or not.
234func (c *Credentials) Authenticated() bool {
235 return c.authenticated
236}
237
238// SetAuthenticated sets the credential as having been successfully authenticated.
239func (c *Credentials) SetAuthenticated(b bool) {
240 c.authenticated = b
241}
242
243// AddAuthzAttribute adds an authorization attribute to the credential.
244func (c *Credentials) AddAuthzAttribute(a string) {
245 c.groupMembership[a] = true
246}
247
248// RemoveAuthzAttribute removes an authorization attribute from the credential.
249func (c *Credentials) RemoveAuthzAttribute(a string) {
250 if _, ok := c.groupMembership[a]; !ok {
251 return
252 }
253 delete(c.groupMembership, a)
254}
255
256// EnableAuthzAttribute toggles an authorization attribute to an enabled state on the credential.
257func (c *Credentials) EnableAuthzAttribute(a string) {
258 if enabled, ok := c.groupMembership[a]; ok && !enabled {
259 c.groupMembership[a] = true
260 }
261}
262
263// DisableAuthzAttribute toggles an authorization attribute to a disabled state on the credential.
264func (c *Credentials) DisableAuthzAttribute(a string) {
265 if enabled, ok := c.groupMembership[a]; ok && enabled {
266 c.groupMembership[a] = false
267 }
268}
269
270// Authorized indicates if the credential has the specified authorizing attribute.
271func (c *Credentials) Authorized(a string) bool {
272 if enabled, ok := c.groupMembership[a]; ok && enabled {
273 return true
274 }
275 return false
276}
277
278// SessionID returns the credential's session ID.
279func (c *Credentials) SessionID() string {
280 return c.sessionID
281}
282
283// Expired indicates if the credential has expired.
284func (c *Credentials) Expired() bool {
285 if !c.validUntil.IsZero() && time.Now().UTC().After(c.validUntil) {
286 return true
287 }
288 return false
289}
290
291// Attributes returns the Credentials' attributes map.
292func (c *Credentials) Attributes() map[string]interface{} {
293 return c.attributes
294}
295
296// SetAttribute sets the value of an attribute.
297func (c *Credentials) SetAttribute(k string, v interface{}) {
298 c.attributes[k] = v
299}
300
301// SetAttributes replaces the attributes map with the one provided.
302func (c *Credentials) SetAttributes(a map[string]interface{}) {
303 c.attributes = a
304}
305
306// RemoveAttribute deletes an attribute from the attribute map that has the key provided.
307func (c *Credentials) RemoveAttribute(k string) {
308 delete(c.attributes, k)
309}