credentials.go 8.3 KB

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