1package ldap 2 3import ( 4 "strings" 5 6 "github.com/hashicorp/vault/logical" 7 "github.com/hashicorp/vault/logical/framework" 8) 9 10func pathUsersList(b *backend) *framework.Path { 11 return &framework.Path{ 12 Pattern: "users/?$", 13 14 Callbacks: map[logical.Operation]framework.OperationFunc{ 15 logical.ListOperation: b.pathUserList, 16 }, 17 18 HelpSynopsis: pathUserHelpSyn, 19 HelpDescription: pathUserHelpDesc, 20 } 21} 22 23func pathUsers(b *backend) *framework.Path { 24 return &framework.Path{ 25 Pattern: `users/(?P<name>.+)`, 26 Fields: map[string]*framework.FieldSchema{ 27 "name": &framework.FieldSchema{ 28 Type: framework.TypeString, 29 Description: "Name of the LDAP user.", 30 }, 31 32 "groups": &framework.FieldSchema{ 33 Type: framework.TypeString, 34 Description: "Comma-separated list of additional groups associated with the user.", 35 }, 36 }, 37 38 Callbacks: map[logical.Operation]framework.OperationFunc{ 39 logical.DeleteOperation: b.pathUserDelete, 40 logical.ReadOperation: b.pathUserRead, 41 logical.UpdateOperation: b.pathUserWrite, 42 }, 43 44 HelpSynopsis: pathUserHelpSyn, 45 HelpDescription: pathUserHelpDesc, 46 } 47} 48 49func (b *backend) User(s logical.Storage, n string) (*UserEntry, error) { 50 entry, err := s.Get("user/" + n) 51 if err != nil { 52 return nil, err 53 } 54 if entry == nil { 55 return nil, nil 56 } 57 58 var result UserEntry 59 if err := entry.DecodeJSON(&result); err != nil { 60 return nil, err 61 } 62 63 return &result, nil 64} 65 66func (b *backend) pathUserDelete( 67 req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 68 err := req.Storage.Delete("user/" + d.Get("name").(string)) 69 if err != nil { 70 return nil, err 71 } 72 73 return nil, nil 74} 75 76func (b *backend) pathUserRead( 77 req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 78 user, err := b.User(req.Storage, d.Get("name").(string)) 79 if err != nil { 80 return nil, err 81 } 82 if user == nil { 83 return nil, nil 84 } 85 86 return &logical.Response{ 87 Data: map[string]interface{}{ 88 "groups": strings.Join(user.Groups, ","), 89 }, 90 }, nil 91} 92 93func (b *backend) pathUserWrite( 94 req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 95 name := d.Get("name").(string) 96 groups := strings.Split(d.Get("groups").(string), ",") 97 for i, g := range groups { 98 groups[i] = strings.TrimSpace(g) 99 } 100 101 // Store it 102 entry, err := logical.StorageEntryJSON("user/"+name, &UserEntry{ 103 Groups: groups, 104 }) 105 if err != nil { 106 return nil, err 107 } 108 if err := req.Storage.Put(entry); err != nil { 109 return nil, err 110 } 111 112 return nil, nil 113} 114 115func (b *backend) pathUserList( 116 req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 117 users, err := req.Storage.List("user/") 118 if err != nil { 119 return nil, err 120 } 121 return logical.ListResponse(users), nil 122} 123 124type UserEntry struct { 125 Groups []string 126} 127 128const pathUserHelpSyn = ` 129Manage additional groups for users allowed to authenticate. 130` 131 132const pathUserHelpDesc = ` 133This endpoint allows you to create, read, update, and delete configuration 134for LDAP users that are allowed to authenticate, in particular associating 135additional groups to them. 136 137Deleting a user will not revoke their auth. To do this, do a revoke on "login/<username>" for 138the usernames you want revoked. 139` 140