Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

identity/oidc: Adds default provider, key, and allow_all assignment #14119

Merged
merged 8 commits into from
Feb 22, 2022
10 changes: 10 additions & 0 deletions vault/identity_store_oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@ func (i *IdentityStore) pathOIDCCreateUpdateKey(ctx context.Context, req *logica

name := d.Get("name").(string)

if name == defaultKeyName {
return logical.ErrorResponse("modification of key %q not allowed",
defaultKeyName), nil
}

i.oidcLock.Lock()
defer i.oidcLock.Unlock()

Expand Down Expand Up @@ -683,6 +688,11 @@ func (i *IdentityStore) pathOIDCDeleteKey(ctx context.Context, req *logical.Requ

targetKeyName := d.Get("name").(string)

if targetKeyName == defaultKeyName {
return logical.ErrorResponse("deletion of key %q not allowed",
defaultKeyName), nil
}

i.oidcLock.Lock()

roleNames, err := i.roleNamesReferencingTargetKeyName(ctx, req, targetKeyName)
Expand Down
160 changes: 153 additions & 7 deletions vault/identity_store_oidc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (
clientSecretPrefix = "hvo_secret_"
codeChallengeMethodPlain = "plain"
codeChallengeMethodS256 = "S256"
defaultProviderName = "default"
defaultKeyName = "default"
allowAllAssignmentName = "allow_all"
austingebauer marked this conversation as resolved.
Show resolved Hide resolved

// Storage path constants
oidcProviderPrefix = "oidc_provider/"
Expand Down Expand Up @@ -266,8 +269,8 @@ func oidcProviderPaths(i *IdentityStore) []*framework.Path {
},
"key": {
Type: framework.TypeString,
Description: "A reference to a named key resource. Cannot be modified after creation.",
Required: true,
Description: "A reference to a named key resource. Cannot be modified after creation. Defaults to the 'default' key.",
Default: "default",
},
"id_token_ttl": {
Type: framework.TypeDurationSecond,
Expand Down Expand Up @@ -654,6 +657,11 @@ func (i *IdentityStore) providersReferencingTargetScopeName(ctx context.Context,
func (i *IdentityStore) pathOIDCCreateUpdateAssignment(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)

if name == allowAllAssignmentName {
return logical.ErrorResponse("modification of assignment %q not allowed",
allowAllAssignmentName), nil
}

i.oidcLock.Lock()
defer i.oidcLock.Unlock()

Expand Down Expand Up @@ -749,6 +757,11 @@ func (i *IdentityStore) getOIDCAssignment(ctx context.Context, s logical.Storage
func (i *IdentityStore) pathOIDCDeleteAssignment(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)

if name == allowAllAssignmentName {
return logical.ErrorResponse("deletion of assignment %q not allowed",
allowAllAssignmentName), nil
}

i.oidcLock.Lock()
defer i.oidcLock.Unlock()

Expand Down Expand Up @@ -1005,10 +1018,6 @@ func (i *IdentityStore) pathOIDCCreateUpdateClient(ctx context.Context, req *log
client.Key = d.Get("key").(string)
}

if client.Key == "" {
return logical.ErrorResponse("the key parameter is required"), nil
}

// enforce key existence on client creation
key, err := i.getNamedKey(ctx, req.Storage, client.Key)
if err != nil {
Expand Down Expand Up @@ -1162,6 +1171,11 @@ func (i *IdentityStore) pathOIDCCreateUpdateProvider(ctx context.Context, req *l
var resp logical.Response
name := d.Get("name").(string)

if name == defaultProviderName {
austingebauer marked this conversation as resolved.
Show resolved Hide resolved
return logical.ErrorResponse("modification of OIDC provider %q not allowed",
defaultProviderName), nil
}

i.oidcLock.Lock()
defer i.oidcLock.Unlock()

Expand Down Expand Up @@ -1348,6 +1362,12 @@ func (i *IdentityStore) getOIDCProvider(ctx context.Context, s logical.Storage,
// pathOIDCDeleteProvider is used to delete a provider
func (i *IdentityStore) pathOIDCDeleteProvider(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)

if name == defaultProviderName {
return logical.ErrorResponse("deletion of OIDC provider %q not allowed",
defaultProviderName), nil
}

return nil, req.Storage.Delete(ctx, providerPath+name)
}

Expand Down Expand Up @@ -1388,7 +1408,7 @@ func (i *IdentityStore) pathOIDCProviderDiscovery(ctx context.Context, req *logi
ResponseTypes: []string{"code"},
Subjects: []string{"public"},
GrantTypes: []string{"authorization_code"},
AuthMethods: []string{"client_secret_basic"},
AuthMethods: []string{"client_secret_basic", "none"},
}

data, err := json.Marshal(disc)
Expand Down Expand Up @@ -2294,6 +2314,10 @@ func (i *IdentityStore) entityHasAssignment(ctx context.Context, s logical.Stora
return false, nil
}

if strutil.StrListContains(assignments, allowAllAssignmentName) {
austingebauer marked this conversation as resolved.
Show resolved Hide resolved
return true, nil
}

// Get the group IDs that the entity is a member of
groups, inheritedGroups, err := i.groupsByEntityID(entity.GetID())
if err != nil {
Expand Down Expand Up @@ -2329,6 +2353,128 @@ func (i *IdentityStore) entityHasAssignment(ctx context.Context, s logical.Stora
return false, nil
}

func defaultOIDCProvider() provider {
return provider{
AllowedClientIDs: []string{"*"},
ScopesSupported: []string{},
}
}

func defaultOIDCKey() namedKey {
return namedKey{
Algorithm: "RS256",
VerificationTTL: 24 * time.Hour,
RotationPeriod: 24 * time.Hour,
NextRotation: time.Now().Add(24 * time.Hour),
AllowedClientIDs: []string{"*"},
}
}

func allowAllAssignment() assignment {
return assignment{
EntityIDs: []string{"*"},
GroupIDs: []string{"*"},
}
}

func (i *IdentityStore) storeOIDCDefaultResources(ctx context.Context) error {
// Store the default provider
storageKey := providerPath + defaultProviderName
entry, err := i.view.Get(ctx, storageKey)
if err != nil {
return err
}
if entry == nil {
entry, err := logical.StorageEntryJSON(storageKey, defaultOIDCProvider())
if err != nil {
return err
}
if err := i.view.Put(ctx, entry); err != nil {
return err
}
}

// Store the default key
storageKey = namedKeyConfigPath + defaultKeyName
entry, err = i.view.Get(ctx, storageKey)
if err != nil {
return err
}
if entry == nil {
defaultKey := defaultOIDCKey()
austingebauer marked this conversation as resolved.
Show resolved Hide resolved

// Generate initial key material for current and next keys
err = defaultKey.generateAndSetKey(ctx, i.Logger(), i.view)
if err != nil {
return err
}
err = defaultKey.generateAndSetNextKey(ctx, i.Logger(), i.view)
if err != nil {
return err
}

// Store the entry
entry, err := logical.StorageEntryJSON(storageKey, defaultKey)
if err != nil {
return err
}
if err := i.view.Put(ctx, entry); err != nil {
return err
}
}

// Store the allow all assignment
storageKey = assignmentPath + allowAllAssignmentName
entry, err = i.view.Get(ctx, storageKey)
if err != nil {
return err
}
if entry == nil {
entry, err := logical.StorageEntryJSON(storageKey, allowAllAssignment())
if err != nil {
return err
}
if err := i.view.Put(ctx, entry); err != nil {
return err
}
}

return nil
}

func (i *IdentityStore) loadOIDCClients(ctx context.Context) error {
i.logger.Debug("identity loading OIDC clients")

clients, err := i.view.List(ctx, clientPath)
if err != nil {
return err
}

txn := i.db.Txn(true)
defer txn.Abort()
for _, name := range clients {
entry, err := i.view.Get(ctx, clientPath+name)
if err != nil {
return err
}
if entry == nil {
continue
}

var client client
if err := entry.DecodeJSON(&client); err != nil {
return err
}

if err := i.memDBUpsertClientInTxn(txn, &client); err != nil {
return err
}
}
txn.Commit()

return nil
}

// clientByID returns the client with the given ID.
func (i *IdentityStore) clientByID(ctx context.Context, s logical.Storage, id string) (*client, error) {
// Read the client from memdb
Expand Down
36 changes: 3 additions & 33 deletions vault/identity_store_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func (c *Core) loadIdentityStoreArtifacts(ctx context.Context) error {
if err := c.identityStore.loadCachedEntitiesOfLocalAliases(ctx); err != nil {
return err
}
if err := c.identityStore.storeOIDCDefaultResources(ctx); err != nil {
austingebauer marked this conversation as resolved.
Show resolved Hide resolved
return err
}

return nil
}
Expand Down Expand Up @@ -90,39 +93,6 @@ func (i *IdentityStore) sanitizeName(name string) string {
return strings.ToLower(name)
}

func (i *IdentityStore) loadOIDCClients(ctx context.Context) error {
i.logger.Debug("identity loading OIDC clients")

clients, err := i.view.List(ctx, clientPath)
if err != nil {
return err
}

txn := i.db.Txn(true)
defer txn.Abort()
for _, name := range clients {
entry, err := i.view.Get(ctx, clientPath+name)
if err != nil {
return err
}
if entry == nil {
continue
}

var client client
if err := entry.DecodeJSON(&client); err != nil {
return err
}

if err := i.memDBUpsertClientInTxn(txn, &client); err != nil {
return err
}
}
txn.Commit()

return nil
}

func (i *IdentityStore) loadGroups(ctx context.Context) error {
i.logger.Debug("identity loading groups")
existing, err := i.groupPacker.View().List(ctx, groupBucketsPrefix)
Expand Down