open-vault/builtin/logical/totp/path_code.go
mymercurialsky 4c0e3c5d2f Implemented TOTP Secret Backend (#2492)
* Initialized basic outline of TOTP backend using Postgresql backend as template

* Updated TOTP backend.go's structure and help string

* Updated TOTP path_roles.go's structure and help strings

* Updated TOTP path_role_create.go's structure and help strings

* Fixed typo in path_roles.go

* Fixed errors in path_role_create.go and path_roles.go

* Added TOTP secret backend information to cli commands

* Fixed build errors in path_roles.go and path_role_create.go

* Changed field values of period and digits from uint to int, added uint conversion of period when generating passwords

* Initialized TOTP test file based on structure of postgresql test file

* Added enforcement of input values

* Added otp library to vendor folder

* Added test steps and cleaned up errors

* Modified read credential test step, not working yet

* Use of vendored package not allowed - Test error

* Removed vendor files for TOTP library

* Revert "Removed vendor files for TOTP library"

This reverts commit fcd030994bc1741dbf490f3995944e091b11da61.

* Hopefully fixed vendor folder issue with TOTP Library

* Added additional tests for TOTP backend

* Cleaned up comments in TOTP backend_test.go

* Added default values of period, algorithm and digits to field schema

* Changed account_name and issuer fields to optional

* Removed MD5 as a hash algorithm option

* Implemented requested pull request changes

* Added ability to validate TOTP codes

* Added ability to have a key generated

* Added skew, qr size and key size parameters

* Reset vendor.json prior to merge

* Readded otp and barcode libraries to vendor.json

* Modified help strings for path_role_create.go

* Fixed test issue in testAccStepReadRole

* Cleaned up error formatting, variable names and path names. Also added some additional documentation

* Moveed barcode and url output to key creation function and did some additional cleanup based on requested changes

* Added ability to pass in TOTP urls

* Added additional tests for TOTP server functions

* Removed unused QRSize, URL and Generate members of keyEntry struct

* Removed unnecessary urlstring variable from pathKeyCreate

* Added website documentation for TOTP secret backend

* Added errors if generate is true and url or key is passed, removed logger from backend, and revised parameter documentation.

* Updated website documentation and added QR example

* Added exported variable and ability to disable QR generation, cleaned up error reporting, changed default skew value, updated documentation and added additional tests

* Updated API documentation to inlude to exported variable and qr size option

* Cleaned up return statements in path_code, added error handling while validating codes and clarified documentation for generate parameters in path_keys
2017-05-04 10:49:42 -07:00

111 lines
2.7 KiB
Go

package totp
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
otplib "github.com/pquerna/otp"
totplib "github.com/pquerna/otp/totp"
)
func pathCode(b *backend) *framework.Path {
return &framework.Path{
Pattern: "code/" + framework.GenericNameRegex("name"),
Fields: map[string]*framework.FieldSchema{
"name": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Name of the key.",
},
"code": &framework.FieldSchema{
Type: framework.TypeString,
Description: "TOTP code to be validated.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.pathReadCode,
logical.UpdateOperation: b.pathValidateCode,
},
HelpSynopsis: pathCodeHelpSyn,
HelpDescription: pathCodeHelpDesc,
}
}
func (b *backend) pathReadCode(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
name := data.Get("name").(string)
// Get the key
key, err := b.Key(req.Storage, name)
if err != nil {
return nil, err
}
if key == nil {
return logical.ErrorResponse(fmt.Sprintf("unknown key: %s", name)), nil
}
// Generate password using totp library
totpToken, err := totplib.GenerateCodeCustom(key.Key, time.Now(), totplib.ValidateOpts{
Period: key.Period,
Digits: key.Digits,
Algorithm: key.Algorithm,
})
if err != nil {
return nil, err
}
// Return the secret
return &logical.Response{
Data: map[string]interface{}{
"code": totpToken,
},
}, nil
}
func (b *backend) pathValidateCode(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
name := data.Get("name").(string)
code := data.Get("code").(string)
// Enforce input value requirements
if code == "" {
return logical.ErrorResponse("the code value is required"), nil
}
// Get the key's stored values
key, err := b.Key(req.Storage, name)
if err != nil {
return nil, err
}
if key == nil {
return logical.ErrorResponse(fmt.Sprintf("unknown key: %s", name)), nil
}
valid, err := totplib.ValidateCustom(code, key.Key, time.Now(), totplib.ValidateOpts{
Period: key.Period,
Skew: key.Skew,
Digits: key.Digits,
Algorithm: key.Algorithm,
})
if err != nil && err != otplib.ErrValidateInputInvalidLength {
return logical.ErrorResponse("an error occured while validating the code"), err
}
return &logical.Response{
Data: map[string]interface{}{
"valid": valid,
},
}, nil
}
const pathCodeHelpSyn = `
Request time-based one-time use password or validate a password for a certain key .
`
const pathCodeHelpDesc = `
This path generates and validates time-based one-time use passwords for a certain key.
`