From 10419845b783c401aa61bb6ac359df4897ec0c8b Mon Sep 17 00:00:00 2001 From: Vishal Nayak Date: Mon, 23 Apr 2018 13:46:14 -0400 Subject: [PATCH] disable identity for local mounts (#4407) --- vault/identity_store.go | 4 ++ vault/identity_store_aliases.go | 4 ++ vault/identity_store_aliases_ext_test.go | 62 ++++++++++++++++++ vault/identity_store_group_aliases.go | 4 ++ .../identity_store_group_aliases_ext_test.go | 64 +++++++++++++++++++ vault/request_handling.go | 4 +- vault/router.go | 2 + 7 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 vault/identity_store_aliases_ext_test.go create mode 100644 vault/identity_store_group_aliases_ext_test.go diff --git a/vault/identity_store.go b/vault/identity_store.go index 518fa123d..6faddace5 100644 --- a/vault/identity_store.go +++ b/vault/identity_store.go @@ -329,6 +329,10 @@ func (i *IdentityStore) CreateOrFetchEntity(alias *logical.Alias) (*identity.Ent return nil, fmt.Errorf("invalid mount accessor %q", alias.MountAccessor) } + if mountValidationResp.MountLocal { + return nil, fmt.Errorf("mount_accessor %q is of a local mount", alias.MountAccessor) + } + if mountValidationResp.MountType != alias.MountType { return nil, fmt.Errorf("mount accessor %q is not a mount of type %q", alias.MountAccessor, alias.MountType) } diff --git a/vault/identity_store_aliases.go b/vault/identity_store_aliases.go index 084c3d597..5fea5de71 100644 --- a/vault/identity_store_aliases.go +++ b/vault/identity_store_aliases.go @@ -235,6 +235,10 @@ func (i *IdentityStore) handleAliasUpdateCommon(req *logical.Request, d *framewo return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", mountAccessor)), nil } + if mountValidationResp.MountLocal { + return logical.ErrorResponse(fmt.Sprintf("mount_accessor %q is of a local mount", mountAccessor)), nil + } + // Get alias metadata metadata, ok, err := d.GetOkErr("metadata") if err != nil { diff --git a/vault/identity_store_aliases_ext_test.go b/vault/identity_store_aliases_ext_test.go new file mode 100644 index 000000000..4051257b0 --- /dev/null +++ b/vault/identity_store_aliases_ext_test.go @@ -0,0 +1,62 @@ +package vault_test + +import ( + "testing" + + "github.com/hashicorp/vault/api" + vaulthttp "github.com/hashicorp/vault/http" + "github.com/hashicorp/vault/logical" + "github.com/hashicorp/vault/vault" + + credLdap "github.com/hashicorp/vault/builtin/credential/ldap" +) + +func TestIdentityStore_EntityAliasLocalMount(t *testing.T) { + coreConfig := &vault.CoreConfig{ + CredentialBackends: map[string]logical.Factory{ + "ldap": credLdap.Factory, + }, + } + cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ + HandlerFunc: vaulthttp.Handler, + }) + cluster.Start() + defer cluster.Cleanup() + + core := cluster.Cores[0].Core + vault.TestWaitActive(t, core) + client := cluster.Cores[0].Client + + // Create a local auth mount + err := client.Sys().EnableAuthWithOptions("ldap", &api.EnableAuthOptions{ + Type: "ldap", + Local: true, + }) + if err != nil { + t.Fatal(err) + } + + // Extract out the mount accessor for LDAP auth + auths, err := client.Sys().ListAuth() + if err != nil { + t.Fatal(err) + } + ldapMountAccessor := auths["ldap/"].Accessor + + // Create an entity + secret, err := client.Logical().Write("identity/entity", nil) + if err != nil { + t.Fatal(err) + } + entityID := secret.Data["id"].(string) + + // Attempt to create an entity alias against a local mount should fail + secret, err = client.Logical().Write("identity/entity-alias", map[string]interface{}{ + "name": "testuser", + "mount_accessor": ldapMountAccessor, + "canonical_id": entityID, + }) + if err == nil { + t.Fatalf("expected error since mount is local") + } +} diff --git a/vault/identity_store_group_aliases.go b/vault/identity_store_group_aliases.go index f59126a50..6c8962417 100644 --- a/vault/identity_store_group_aliases.go +++ b/vault/identity_store_group_aliases.go @@ -158,6 +158,10 @@ func (i *IdentityStore) handleGroupAliasUpdateCommon(req *logical.Request, d *fr return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", mountAccessor)), nil } + if mountValidationResp.MountLocal { + return logical.ErrorResponse(fmt.Sprintf("mount_accessor %q is of a local mount", mountAccessor)), nil + } + groupAliasByFactors, err := i.MemDBAliasByFactors(mountValidationResp.MountAccessor, groupAliasName, false, true) if err != nil { return nil, err diff --git a/vault/identity_store_group_aliases_ext_test.go b/vault/identity_store_group_aliases_ext_test.go new file mode 100644 index 000000000..bfed17635 --- /dev/null +++ b/vault/identity_store_group_aliases_ext_test.go @@ -0,0 +1,64 @@ +package vault_test + +import ( + "testing" + + "github.com/hashicorp/vault/api" + vaulthttp "github.com/hashicorp/vault/http" + "github.com/hashicorp/vault/logical" + "github.com/hashicorp/vault/vault" + + credLdap "github.com/hashicorp/vault/builtin/credential/ldap" +) + +func TestIdentityStore_GroupAliasLocalMount(t *testing.T) { + coreConfig := &vault.CoreConfig{ + CredentialBackends: map[string]logical.Factory{ + "ldap": credLdap.Factory, + }, + } + cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ + HandlerFunc: vaulthttp.Handler, + }) + cluster.Start() + defer cluster.Cleanup() + + core := cluster.Cores[0].Core + vault.TestWaitActive(t, core) + client := cluster.Cores[0].Client + + // Create a local auth mount + err := client.Sys().EnableAuthWithOptions("ldap", &api.EnableAuthOptions{ + Type: "ldap", + Local: true, + }) + if err != nil { + t.Fatal(err) + } + + // Extract out the mount accessor for LDAP auth + auths, err := client.Sys().ListAuth() + if err != nil { + t.Fatal(err) + } + ldapMountAccessor := auths["ldap/"].Accessor + + // Create an external group + secret, err := client.Logical().Write("identity/group", map[string]interface{}{ + "type": "external", + }) + if err != nil { + t.Fatal(err) + } + groupID := secret.Data["id"].(string) + + // Attempt to create a group alias against a local mount should fail + secret, err = client.Logical().Write("identity/group-alias", map[string]interface{}{ + "name": "testuser", + "mount_accessor": ldapMountAccessor, + "canonical_id": groupID, + }) + if err == nil { + t.Fatalf("expected error since mount is local") + } +} diff --git a/vault/request_handling.go b/vault/request_handling.go index 1431d041d..b03833085 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -496,7 +496,9 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re var entity *identity.Entity auth = resp.Auth - if auth.Alias != nil { + mEntry := c.router.MatchingMountEntry(req.Path) + + if auth.Alias != nil && mEntry != nil && !mEntry.Local { // Overwrite the mount type and mount path in the alias // information auth.Alias.MountType = req.MountType diff --git a/vault/router.go b/vault/router.go index 4cbcabf81..32b036824 100644 --- a/vault/router.go +++ b/vault/router.go @@ -61,6 +61,7 @@ type validateMountResponse struct { MountType string `json:"mount_type" structs:"mount_type" mapstructure:"mount_type"` MountAccessor string `json:"mount_accessor" structs:"mount_accessor" mapstructure:"mount_accessor"` MountPath string `json:"mount_path" structs:"mount_path" mapstructure:"mount_path"` + MountLocal bool `json:"mount_local" structs:"mount_local" mapstructure:"mount_local"` } // validateMountByAccessor returns the mount type and ID for a given mount @@ -84,6 +85,7 @@ func (r *Router) validateMountByAccessor(accessor string) *validateMountResponse MountAccessor: mountEntry.Accessor, MountType: mountEntry.Type, MountPath: mountPath, + MountLocal: mountEntry.Local, } }