Skip to content

Commit

Permalink
Provide Descriptive Error when Enterprise-only Paths Called in Open-s…
Browse files Browse the repository at this point in the history
…ource Version (hashicorp#18870)

* define ent paths in OSS codebase with common handler

* fixup! define ent paths in OSS codebase with common handler

* add missing path

* retain existing behaviour for replication/status path

* remove commented out path
  • Loading branch information
Marc Boudreau authored Apr 21, 2023
1 parent 77f83d9 commit d11f7a2
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 19 deletions.
3 changes: 3 additions & 0 deletions changelog/18870.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
core:provide more descriptive error message when calling enterprise feature paths in open-source
```
176 changes: 157 additions & 19 deletions vault/logical_system_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,166 @@ var (
}
}

entPaths = func(b *SystemBackend) []*framework.Path {
return []*framework.Path{
{
Pattern: "replication/status",

DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "replication",
OperationVerb: "status",
},
entPaths = entStubPaths
entStubPaths = func(b *SystemBackend) []*framework.Path {
buildEnterpriseOnlyPaths := func(paths map[string][]logical.Operation) []*framework.Path {
var results []*framework.Path
for pattern, operations := range paths {
operationsMap := map[logical.Operation]framework.OperationHandler{}

for _, operation := range operations {
operationsMap[operation] = &framework.PathOperation{
Callback: func(context.Context, *logical.Request, *framework.FieldData) (*logical.Response, error) {
return logical.ErrorResponse("enterprise-only feature"), logical.ErrUnsupportedPath
},
}
}

results = append(results, &framework.Path{
Pattern: pattern,
Operations: operationsMap,
})
}

return results
}

var paths []*framework.Path

// license paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"license/status$": {logical.ReadOperation},
})...)

// group-policy-application paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"config/group-policy-application$": {logical.ReadOperation, logical.UpdateOperation},
})...)

// namespaces paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"namespaces/?$": {logical.ListOperation},
"namespaces/api-lock/lock" + framework.OptionalParamRegex("path"): {logical.UpdateOperation},
"namespaces/api-lock/unlock" + framework.OptionalParamRegex("path"): {logical.UpdateOperation},
"namespaces/(?P<path>.+?)": {logical.DeleteOperation, logical.PatchOperation, logical.ReadOperation, logical.UpdateOperation},
})...)

Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
resp := &logical.Response{
Data: map[string]interface{}{
"mode": "disabled",
},
}
return resp, nil
},
// replication paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"replication/performance/primary/enable": {logical.UpdateOperation},
"replication/dr/primary/enable": {logical.UpdateOperation},
"replication/performance/primary/demote": {logical.UpdateOperation},
"replication/dr/primary/demote": {logical.UpdateOperation},
"replication/performance/primary/disable": {logical.UpdateOperation},
"replication/dr/primary/disable": {logical.UpdateOperation},
"replication/performance/primary/secondary-token": {logical.UpdateOperation},
"replication/dr/primary/secondary-token": {logical.UpdateOperation},
"replication/performance/primary/revoke-secondary": {logical.UpdateOperation},
"replication/dr/primary/revoke-secondary": {logical.UpdateOperation},
"replication/performance/secondary/generate-public-key": {logical.UpdateOperation},
"replication/dr/secondary/generate-public-key": {logical.UpdateOperation},
"replication/performance/secondary/enable": {logical.UpdateOperation},
"replication/dr/secondary/enable": {logical.UpdateOperation},
"replication/performance/secondary/promote": {logical.UpdateOperation},
"replication/dr/secondary/promote": {logical.UpdateOperation},
"replication/performance/secondary/disable": {logical.UpdateOperation},
"replication/dr/secondary/disable": {logical.UpdateOperation},
"replication/dr/secondary/operation-token/delete": {logical.UpdateOperation},
"replication/performance/secondary/update-primary": {logical.UpdateOperation},
"replication/dr/secondary/update-primary": {logical.UpdateOperation},
"replication/dr/secondary/license/status": {logical.ReadOperation},
"replication/dr/secondary/config/reload/(?P<subsystem>.+)": {logical.UpdateOperation},
"replication/recover": {logical.UpdateOperation},
"replication/dr/secondary/recover": {logical.UpdateOperation},
"replication/dr/secondary/reindex": {logical.UpdateOperation},
"replication/reindex": {logical.UpdateOperation},
"replication/dr/status": {logical.ReadOperation},
"replication/performance/status": {logical.ReadOperation},
"replication/primary/enable": {logical.UpdateOperation},
"replication/primary/demote": {logical.UpdateOperation},
"replication/primary/disable": {logical.UpdateOperation},
"replication/primary/secondary-token": {logical.UpdateOperation},
"replication/performance/primary/paths-filter/" + framework.GenericNameRegex("id"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"replication/performance/primary/dynamic-filter/" + framework.GenericNameRegex("id"): {logical.ReadOperation},
"replication/primary/revoke-secondary": {logical.UpdateOperation},
"replication/secondary/enable": {logical.UpdateOperation},
"replication/secondary/promote": {logical.UpdateOperation},
"replication/secondary/disable": {logical.UpdateOperation},
"replication/secondary/update-primary": {logical.UpdateOperation},
"replication/performance/secondary/dynamic-filter/" + framework.GenericNameRegex("id"): {logical.ReadOperation},
})...)
// This path, though an enterprise path, has always been handled in OSS.
paths = append(paths, &framework.Path{
Pattern: "replication/status",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
resp := &logical.Response{
Data: map[string]interface{}{
"mode": "disabled",
},
}
return resp, nil
},
},
}
})

// seal paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"sealwrap/rewrap": {logical.ReadOperation, logical.UpdateOperation},
})...)

// mfa paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"mfa/method/?": {logical.ListOperation},
"mfa/method/totp/" + framework.GenericNameRegex("name") + "/generate$": {logical.ReadOperation},
"mfa/method/totp/" + framework.GenericNameRegex("name") + "/admin-generate$": {logical.UpdateOperation},
"mfa/method/totp/" + framework.GenericNameRegex("name") + "/admin-destroy$": {logical.UpdateOperation},
"mfa/method/totp/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"mfa/method/okta/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"mfa/method/duo/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"mfa/method/pingid/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
})...)

// control-group paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"control-group/authorize": {logical.UpdateOperation},
"control-group/request": {logical.UpdateOperation},
"config/control-group": {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
})...)

// sentinel paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"policies/rgp/?$": {logical.ListOperation},
"policies/rgp/(?P<name>.+)": {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"policies/egp/?$": {logical.ListOperation},
"policies/egp/(?P<name>.+)": {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
})...)

// plugins reload status paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"plugins/reload/backend/status$": {logical.ReadOperation},
})...)

// quotas paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"quotas/lease-count/?$": {logical.ListOperation},
"quotas/lease-count/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
})...)

// raft auto-snapshot paths
paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"storage/raft/snapshot-auto/config/": {logical.ListOperation},
"storage/raft/snapshot-auto/config/" + framework.GenericNameRegex("name"): {logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"storage/raft/snapshot-auto/status/" + framework.GenericNameRegex("name"): {logical.ReadOperation},
})...)

paths = append(paths, buildEnterpriseOnlyPaths(map[string][]logical.Operation{
"managed-keys/" + framework.GenericNameRegex("type") + "/?": {logical.ListOperation},
"managed-keys/" + framework.GenericNameRegex("type") + "/" + framework.GenericNameRegex("name"): {logical.CreateOperation, logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation},
"managed-keys/" + framework.GenericNameRegex("type") + "/" + framework.GenericNameRegex("name") + "/test/sign": {logical.CreateOperation, logical.UpdateOperation},
})...)

return paths
}
handleGlobalPluginReload = func(context.Context, *Core, string, string, []string) error {
return nil
Expand Down

0 comments on commit d11f7a2

Please sign in to comment.