credential/userpass: login

This commit is contained in:
Mitchell Hashimoto 2015-04-19 15:06:29 -07:00
parent fedda20c41
commit 0aec679bb4
5 changed files with 90 additions and 5 deletions

View File

@ -49,6 +49,7 @@ func testAccMap(t *testing.T) logicaltest.TestStep {
},
}
}
func testAccLogin(t *testing.T) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.WriteOperation,

View File

@ -20,11 +20,12 @@ func Backend() *framework.Backend {
},
Unauthenticated: []string{
"login",
"login/*",
},
},
Paths: append([]*framework.Path{
pathLogin(&b),
pathUsers(&b),
}),
}

View File

@ -9,6 +9,18 @@ import (
"github.com/mitchellh/mapstructure"
)
func TestBackend_basic(t *testing.T) {
b := Backend()
logicaltest.Test(t, logicaltest.TestCase{
Backend: b,
Steps: []logicaltest.TestStep{
testAccStepUser(t, "web", "password", "foo"),
testAccStepLogin(t, "web", "password"),
},
})
}
func TestBackend_userCrud(t *testing.T) {
b := Backend()
@ -23,6 +35,19 @@ func TestBackend_userCrud(t *testing.T) {
})
}
func testAccStepLogin(t *testing.T, user string, pass string) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.WriteOperation,
Path: "login/" + user,
Data: map[string]interface{}{
"password": pass,
},
Unauthenticated: true,
Check: logicaltest.TestCheckAuth([]string{"foo"}),
}
}
func testAccStepUser(
t *testing.T, name string, password string, policies string) logicaltest.TestStep {
return logicaltest.TestStep{

View File

@ -0,0 +1,53 @@
package userpass
import (
"strings"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
func pathLogin(b *backend) *framework.Path {
return &framework.Path{
Pattern: `login/(?P<name>\w+)`,
Fields: map[string]*framework.FieldSchema{
"name": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Username of the user.",
},
"password": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Password for this user.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.WriteOperation: b.pathLogin,
},
}
}
func (b *backend) pathLogin(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
username := strings.ToLower(d.Get("name").(string))
// Get the user and validate auth
user, err := b.User(req.Storage, username)
if err != nil {
return nil, err
}
if user == nil || user.Password != d.Get("password").(string) {
return logical.ErrorResponse("unknown username or password"), nil
}
return &logical.Response{
Auth: &logical.Auth{
Policies: user.Policies,
Metadata: map[string]string{
"username": username,
},
DisplayName: username,
},
}, nil
}

View File

@ -39,7 +39,7 @@ func pathUsers(b *backend) *framework.Path {
}
func (b *backend) User(s logical.Storage, n string) (*UserEntry, error) {
entry, err := s.Get("user/" + n)
entry, err := s.Get("user/" + strings.ToLower(n))
if err != nil {
return nil, err
}
@ -57,7 +57,7 @@ func (b *backend) User(s logical.Storage, n string) (*UserEntry, error) {
func (b *backend) pathUserDelete(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
err := req.Storage.Delete("user/" + d.Get("name").(string))
err := req.Storage.Delete("user/" + strings.ToLower(d.Get("name").(string)))
if err != nil {
return nil, err
}
@ -67,7 +67,7 @@ func (b *backend) pathUserDelete(
func (b *backend) pathUserRead(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
user, err := b.User(req.Storage, d.Get("name").(string))
user, err := b.User(req.Storage, strings.ToLower(d.Get("name").(string)))
if err != nil {
return nil, err
}
@ -84,7 +84,7 @@ func (b *backend) pathUserRead(
func (b *backend) pathUserWrite(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)
name := strings.ToLower(d.Get("name").(string))
policies := strings.Split(d.Get("policies").(string), ",")
for i, p := range policies {
policies[i] = strings.TrimSpace(p)
@ -117,4 +117,9 @@ Manage users allowed to authenticate.
const pathUserHelpDesc = `
This endpoint allows you to create, read, update, and delete users
that are allowed to authenticate.
Deleting a user will not revoke auth for prior authenticated users
with that name. To do this, do a revoke on "login/<username>" for
the username you want revoked. If you don't need to revoke login immediately,
then the next renew will cause the lease to expire.
`