Skip to content

Commit

Permalink
Fix bug where updates to config would fail is password isn't provided (
Browse files Browse the repository at this point in the history
…#91) (#93)

* Fix bug where updates to config would fail is password isn't provided

* Make test clearer
  • Loading branch information
jasonodonnell authored Dec 1, 2022
1 parent 2cb8c53 commit fd556b4
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 17 deletions.
40 changes: 40 additions & 0 deletions plugin/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func TestBackend(t *testing.T) {
t.Run("write config", WriteConfig)
t.Run("read config", ReadConfig)
t.Run("delete config", DeleteConfig)
t.Run("update config", UpdateConfig)

// Plant a config for further testing.
t.Run("plant config", PlantConfig)
Expand Down Expand Up @@ -82,6 +83,45 @@ func WriteConfig(t *testing.T) {
}
}

func UpdateConfig(t *testing.T) {
req := &logical.Request{
Operation: logical.UpdateOperation,
Path: configPath,
Storage: testStorage,
Data: map[string]interface{}{
"binddn": "tester",
"password": "pa$$w0rd",
"url": "ldap://138.91.247.105",
"userdn": "dc=example,dc=com",
"formatter": "mycustom{{PASSWORD}}",
"last_rotation_tolerance": 10,
},
}
resp, err := testBackend.HandleRequest(testCtx, req)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatal(err)
}
if resp != nil {
t.Fatal("expected no response because Vault generally doesn't return it for posts")
}

req = &logical.Request{
Operation: logical.UpdateOperation,
Path: configPath,
Storage: testStorage,
Data: map[string]interface{}{
"certificate": validCertificate,
},
}
resp, err = testBackend.HandleRequest(testCtx, req)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatal(err)
}
if resp != nil {
t.Fatal("expected no response because Vault generally doesn't return it for posts")
}
}

func ReadConfig(t *testing.T) {
req := &logical.Request{
Operation: logical.ReadOperation,
Expand Down
10 changes: 5 additions & 5 deletions plugin/checkout_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func (h *checkOutHandler) CheckIn(ctx context.Context, storage logical.Storage,
}

// LoadCheckOut returns either:
// - A *CheckOut and nil error if the serviceAccountName is currently managed by this engine.
// - A nil *Checkout and errNotFound if the serviceAccountName is not currently managed by this engine.
// - A *CheckOut and nil error if the serviceAccountName is currently managed by this engine.
// - A nil *Checkout and errNotFound if the serviceAccountName is not currently managed by this engine.
func (h *checkOutHandler) LoadCheckOut(ctx context.Context, storage logical.Storage, serviceAccountName string) (*CheckOut, error) {
if ctx == nil {
return nil, errors.New("ctx must be provided")
Expand Down Expand Up @@ -174,9 +174,9 @@ func (h *checkOutHandler) Delete(ctx context.Context, storage logical.Storage, s

// retrievePassword is a utility function for grabbing a service account's password from storage.
// retrievePassword will return:
// - "password", nil if it was successfully able to retrieve the password.
// - errNotFound if there's no password presently.
// - Some other err if it was unable to complete successfully.
// - "password", nil if it was successfully able to retrieve the password.
// - errNotFound if there's no password presently.
// - Some other err if it was unable to complete successfully.
func retrievePassword(ctx context.Context, storage logical.Storage, serviceAccountName string) (string, error) {
entry, err := storage.Get(ctx, passwordStoragePrefix+serviceAccountName)
if err != nil {
Expand Down
9 changes: 4 additions & 5 deletions plugin/client/fieldregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import (
//
// Example: Accessing constants
//
// FieldRegistry.AccountExpires
// FieldRegistry.BadPasswordCount
// FieldRegistry.AccountExpires
// FieldRegistry.BadPasswordCount
//
// Example: Utility methods
//
// FieldRegistry.List()
// FieldRegistry.Parse("givenName")
//
// FieldRegistry.List()
// FieldRegistry.Parse("givenName")
var FieldRegistry = newFieldRegistry()

// newFieldRegistry iterates through all the fields in the registry,
Expand Down
10 changes: 5 additions & 5 deletions plugin/client/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ func ParseTicks(ticks string) (time.Time, error) {
// TicksToTime converts an ActiveDirectory time in ticks to a time.
// This algorithm is summarized as:
//
// Many dates are saved in Active Directory as Large Integer values.
// These attributes represent dates as the number of 100-nanosecond intervals since 12:00 AM January 1, 1601.
// 100-nanosecond intervals, equal to 0.0000001 seconds, are also called ticks.
// Dates in Active Directory are always saved in Coordinated Universal Time, or UTC.
// More: https://social.technet.microsoft.com/wiki/contents/articles/31135.active-directory-large-integer-attributes.aspx
// Many dates are saved in Active Directory as Large Integer values.
// These attributes represent dates as the number of 100-nanosecond intervals since 12:00 AM January 1, 1601.
// 100-nanosecond intervals, equal to 0.0000001 seconds, are also called ticks.
// Dates in Active Directory are always saved in Coordinated Universal Time, or UTC.
// More: https://social.technet.microsoft.com/wiki/contents/articles/31135.active-directory-large-integer-attributes.aspx
//
// If we directly follow the above algorithm we encounter time.Duration limits of 290 years and int overflow issues.
// Thus below, we carefully sidestep those.
Expand Down
20 changes: 19 additions & 1 deletion plugin/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,29 @@ func (b *backend) configFields() map[string]*framework.FieldSchema {
}

func (b *backend) configUpdateOperation(ctx context.Context, req *logical.Request, fieldData *framework.FieldData) (*logical.Response, error) {

conf, err := readConfig(ctx, req.Storage)
if err != nil {
return nil, err
}

if conf == nil {
conf = new(configuration)
conf.ADConf = new(client.ADConf)
}

// Use the existing ldap client config if it is set
var existing *ldaputil.ConfigEntry
if conf.ADConf != nil && conf.ADConf.ConfigEntry != nil {
existing = conf.ADConf.ConfigEntry
}

// Build and validate the ldap conf.
activeDirectoryConf, err := ldaputil.NewConfigEntry(nil, fieldData)
activeDirectoryConf, err := ldaputil.NewConfigEntry(existing, fieldData)
if err != nil {
return nil, err
}

if err := activeDirectoryConf.Validate(); err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion plugin/path_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package plugin

import (
"context"
"testing"

"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/assert"
"testing"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
Expand Down

0 comments on commit fd556b4

Please sign in to comment.