2015-07-28 01:05:06 +00:00
|
|
|
package mfa
|
|
|
|
|
|
|
|
import (
|
2018-01-08 20:26:13 +00:00
|
|
|
"context"
|
2015-07-28 01:05:06 +00:00
|
|
|
"testing"
|
|
|
|
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
|
|
|
logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical"
|
2015-07-28 01:05:06 +00:00
|
|
|
)
|
|
|
|
|
2015-07-31 00:16:53 +00:00
|
|
|
// MakeTestBackend creates a simple MFA enabled backend.
|
|
|
|
// Login (before MFA) always succeeds with policy "foo".
|
|
|
|
// An MFA "test" type is added to mfa.handlers that succeeds
|
|
|
|
// if MFA method is "accept", otherwise it rejects.
|
2015-07-28 01:05:06 +00:00
|
|
|
func MakeTestBackend() *framework.Backend {
|
|
|
|
handlers["test"] = testMFAHandler
|
|
|
|
b := &framework.Backend{
|
|
|
|
Help: "",
|
|
|
|
|
|
|
|
PathsSpecial: &logical.Paths{
|
2015-07-31 00:16:53 +00:00
|
|
|
Root: MFARootPaths(),
|
2015-07-28 01:05:06 +00:00
|
|
|
Unauthenticated: []string{
|
|
|
|
"login",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Paths: MFAPaths(nil, testPathLogin()),
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2016-04-05 19:10:44 +00:00
|
|
|
func testPathLogin() *framework.Path {
|
2015-07-28 01:05:06 +00:00
|
|
|
return &framework.Path{
|
|
|
|
Pattern: `login`,
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"username": &framework.FieldSchema{
|
2016-04-05 19:10:44 +00:00
|
|
|
Type: framework.TypeString,
|
2015-07-28 01:05:06 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2016-01-07 15:30:47 +00:00
|
|
|
logical.UpdateOperation: testPathLoginHandler,
|
2015-07-28 01:05:06 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-08 20:26:13 +00:00
|
|
|
func testPathLoginHandler(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
2015-07-28 01:05:06 +00:00
|
|
|
username := d.Get("username").(string)
|
|
|
|
|
|
|
|
return &logical.Response{
|
|
|
|
Auth: &logical.Auth{
|
|
|
|
Policies: []string{"foo"},
|
|
|
|
Metadata: map[string]string{
|
|
|
|
"username": username,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
func testMFAHandler(ctx context.Context, req *logical.Request, d *framework.FieldData, resp *logical.Response) (
|
2015-07-28 01:05:06 +00:00
|
|
|
*logical.Response, error) {
|
|
|
|
if d.Get("method").(string) != "accept" {
|
|
|
|
return logical.ErrorResponse("Deny access"), nil
|
|
|
|
} else {
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMFALogin(t *testing.T) {
|
|
|
|
b := MakeTestBackend()
|
|
|
|
|
|
|
|
logicaltest.Test(t, logicaltest.TestCase{
|
2016-04-05 19:10:44 +00:00
|
|
|
AcceptanceTest: true,
|
2018-11-07 01:21:24 +00:00
|
|
|
LogicalBackend: b,
|
2015-07-28 01:05:06 +00:00
|
|
|
Steps: []logicaltest.TestStep{
|
|
|
|
testAccStepEnableMFA(t),
|
|
|
|
testAccStepLogin(t, "user"),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMFALoginDenied(t *testing.T) {
|
|
|
|
b := MakeTestBackend()
|
|
|
|
|
|
|
|
logicaltest.Test(t, logicaltest.TestCase{
|
2016-04-05 19:10:44 +00:00
|
|
|
AcceptanceTest: true,
|
2018-11-07 01:21:24 +00:00
|
|
|
LogicalBackend: b,
|
2015-07-28 01:05:06 +00:00
|
|
|
Steps: []logicaltest.TestStep{
|
|
|
|
testAccStepEnableMFA(t),
|
|
|
|
testAccStepLoginDenied(t, "user"),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccStepEnableMFA(t *testing.T) logicaltest.TestStep {
|
|
|
|
return logicaltest.TestStep{
|
2016-01-07 15:30:47 +00:00
|
|
|
Operation: logical.UpdateOperation,
|
2016-04-05 19:10:44 +00:00
|
|
|
Path: "mfa_config",
|
2015-07-28 01:05:06 +00:00
|
|
|
Data: map[string]interface{}{
|
|
|
|
"type": "test",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccStepLogin(t *testing.T, username string) logicaltest.TestStep {
|
|
|
|
return logicaltest.TestStep{
|
2016-01-07 15:30:47 +00:00
|
|
|
Operation: logical.UpdateOperation,
|
2016-04-05 19:10:44 +00:00
|
|
|
Path: "login",
|
2015-07-28 01:05:06 +00:00
|
|
|
Data: map[string]interface{}{
|
2016-04-05 19:10:44 +00:00
|
|
|
"method": "accept",
|
2015-07-28 01:05:06 +00:00
|
|
|
"username": username,
|
|
|
|
},
|
|
|
|
Unauthenticated: true,
|
2016-04-05 19:10:44 +00:00
|
|
|
Check: logicaltest.TestCheckAuth([]string{"foo"}),
|
2015-07-28 01:05:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccStepLoginDenied(t *testing.T, username string) logicaltest.TestStep {
|
|
|
|
return logicaltest.TestStep{
|
2016-01-07 15:30:47 +00:00
|
|
|
Operation: logical.UpdateOperation,
|
2016-04-05 19:10:44 +00:00
|
|
|
Path: "login",
|
2015-07-28 01:05:06 +00:00
|
|
|
Data: map[string]interface{}{
|
2016-04-05 19:10:44 +00:00
|
|
|
"method": "deny",
|
2015-07-28 01:05:06 +00:00
|
|
|
"username": username,
|
|
|
|
},
|
|
|
|
Unauthenticated: true,
|
2016-04-05 19:10:44 +00:00
|
|
|
Check: logicaltest.TestCheckError(),
|
2015-07-28 01:05:06 +00:00
|
|
|
}
|
|
|
|
}
|