From ab269aef60c383bb75f6f54b350c8da13772da30 Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Thu, 7 May 2015 01:48:59 +0200 Subject: [PATCH] auth/ldap: add configuration path for groups --- builtin/credential/ldap/backend.go | 2 + builtin/credential/ldap/path_groups.go | 118 +++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 builtin/credential/ldap/path_groups.go diff --git a/builtin/credential/ldap/backend.go b/builtin/credential/ldap/backend.go index 619d55c82b..0c81e85bd4 100644 --- a/builtin/credential/ldap/backend.go +++ b/builtin/credential/ldap/backend.go @@ -17,6 +17,7 @@ func Backend() *framework.Backend { PathsSpecial: &logical.Paths{ Root: []string{ "config", + "groups/*", }, Unauthenticated: []string{ @@ -27,6 +28,7 @@ func Backend() *framework.Backend { Paths: append([]*framework.Path{ pathLogin(&b), pathConfig(&b), + pathGroups(&b), }), // AuthRenew: b.pathLoginRenew, diff --git a/builtin/credential/ldap/path_groups.go b/builtin/credential/ldap/path_groups.go new file mode 100644 index 0000000000..670d58c84e --- /dev/null +++ b/builtin/credential/ldap/path_groups.go @@ -0,0 +1,118 @@ +package ldap + +import ( + "strings" + + "github.com/hashicorp/vault/logical" + "github.com/hashicorp/vault/logical/framework" +) + +func pathGroups(b *backend) *framework.Path { + return &framework.Path{ + Pattern: `groups/(?P\w+)`, + Fields: map[string]*framework.FieldSchema{ + "name": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "Name of the LDAP group.", + }, + + "policies": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "Comma-separated list of policies associated to the group.", + }, + }, + + Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.DeleteOperation: b.pathGroupDelete, + logical.ReadOperation: b.pathGroupRead, + logical.WriteOperation: b.pathGroupWrite, + }, + + HelpSynopsis: pathGroupHelpSyn, + HelpDescription: pathGroupHelpDesc, + } +} + +func (b *backend) Group(s logical.Storage, n string) (*GroupEntry, error) { + entry, err := s.Get("group/" + n) + if err != nil { + return nil, err + } + if entry == nil { + return nil, nil + } + + var result GroupEntry + if err := entry.DecodeJSON(&result); err != nil { + return nil, err + } + + return &result, nil +} + +func (b *backend) pathGroupDelete( + req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + err := req.Storage.Delete("group/" + d.Get("name").(string)) + if err != nil { + return nil, err + } + + return nil, nil +} + +func (b *backend) pathGroupRead( + req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + group, err := b.Group(req.Storage, d.Get("name").(string)) + if err != nil { + return nil, err + } + if group == nil { + return nil, nil + } + + return &logical.Response{ + Data: map[string]interface{}{ + "policies": strings.Join(group.Policies, ","), + }, + }, nil +} + +func (b *backend) pathGroupWrite( + req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + name := d.Get("name").(string) + policies := strings.Split(d.Get("policies").(string), ",") + for i, p := range policies { + policies[i] = strings.TrimSpace(p) + } + + // Store it + entry, err := logical.StorageEntryJSON("group/"+name, &GroupEntry{ + Policies: policies, + }) + if err != nil { + return nil, err + } + if err := req.Storage.Put(entry); err != nil { + return nil, err + } + + return nil, nil +} + +type GroupEntry struct { + Policies []string +} + +const pathGroupHelpSyn = ` +Manage users allowed to authenticate. +` + +const pathGroupHelpDesc = ` +This endpoint allows you to create, read, update, and delete configuration +for LDAP groups that are allowed to authenticate, and associate policies to +them. + +Deleting a group will not revoke auth for prior authenticated users in that +group. To do this, do a revoke on "login/" for +the usernames you want revoked. +`