mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 02:02:43 +00:00 
			
		
		
		
	Plugins: Fix file permissions check to always use the correct path (#17340)
* Add failing test for when command != plugin name * wrapFactoryCheckPerms uses pluginCatalog.Get to fetch the correct command * Use filepath.Rel for consistency with plugin read API handler
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/17340.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/17340.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | ```release-note:bug | ||||||
|  | plugins: Corrected the path to check permissions on when the registered plugin name does not match the plugin binary's filename. | ||||||
|  | ``` | ||||||
| @@ -509,11 +509,84 @@ func TestExternalPlugin_getBackendTypeVersion(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestExternalPlugin_CheckFilePermissions(t *testing.T) { | ||||||
|  | 	// Turn on the check. | ||||||
|  | 	if err := os.Setenv(consts.VaultEnableFilePermissionsCheckEnv, "true"); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer func() { | ||||||
|  | 		if err := os.Unsetenv(consts.VaultEnableFilePermissionsCheckEnv); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	for name, tc := range map[string]struct { | ||||||
|  | 		pluginNameFmt string | ||||||
|  | 		pluginType    consts.PluginType | ||||||
|  | 		pluginVersion string | ||||||
|  | 	}{ | ||||||
|  | 		"plugin name and file name match": { | ||||||
|  | 			pluginNameFmt: "%s", | ||||||
|  | 			pluginType:    consts.PluginTypeCredential, | ||||||
|  | 		}, | ||||||
|  | 		"plugin name and file name mismatch": { | ||||||
|  | 			pluginNameFmt: "%s-foo", | ||||||
|  | 			pluginType:    consts.PluginTypeSecrets, | ||||||
|  | 		}, | ||||||
|  | 		"plugin name has slash": { | ||||||
|  | 			pluginNameFmt: "%s/foo", | ||||||
|  | 			pluginType:    consts.PluginTypeCredential, | ||||||
|  | 		}, | ||||||
|  | 		"plugin with version": { | ||||||
|  | 			pluginNameFmt: "%s/foo", | ||||||
|  | 			pluginType:    consts.PluginTypeCredential, | ||||||
|  | 			pluginVersion: "v1.2.3", | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		t.Run(name, func(t *testing.T) { | ||||||
|  | 			c, pluginName, pluginSHA256 := testCoreWithPlugin(t, tc.pluginType, tc.pluginVersion) | ||||||
|  | 			registeredPluginName := fmt.Sprintf(tc.pluginNameFmt, pluginName) | ||||||
|  |  | ||||||
|  | 			// Permissions will be checked once during registration. | ||||||
|  | 			req := logical.TestRequest(t, logical.UpdateOperation, fmt.Sprintf("plugins/catalog/%s/%s", tc.pluginType.String(), registeredPluginName)) | ||||||
|  | 			req.Data = map[string]interface{}{ | ||||||
|  | 				"command": pluginName, | ||||||
|  | 				"sha256":  pluginSHA256, | ||||||
|  | 				"version": tc.pluginVersion, | ||||||
|  | 			} | ||||||
|  | 			resp, err := c.systemBackend.HandleRequest(namespace.RootContext(nil), req) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 			if resp.Error() != nil { | ||||||
|  | 				t.Fatal(resp.Error()) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Now attempt to mount the plugin, which should trigger checking the permissions again. | ||||||
|  | 			req = logical.TestRequest(t, logical.UpdateOperation, mountTable(tc.pluginType)) | ||||||
|  | 			req.Data = map[string]interface{}{ | ||||||
|  | 				"type": registeredPluginName, | ||||||
|  | 			} | ||||||
|  | 			if tc.pluginVersion != "" { | ||||||
|  | 				req.Data["config"] = map[string]interface{}{ | ||||||
|  | 					"plugin_version": tc.pluginVersion, | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			resp, err = c.systemBackend.HandleRequest(namespace.RootContext(nil), req) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 			if resp.Error() != nil { | ||||||
|  | 				t.Fatal(resp.Error()) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func registerPlugin(t *testing.T, sys *SystemBackend, pluginName, pluginType, version, sha string) { | func registerPlugin(t *testing.T, sys *SystemBackend, pluginName, pluginType, version, sha string) { | ||||||
| 	t.Helper() | 	t.Helper() | ||||||
| 	req := logical.TestRequest(t, logical.UpdateOperation, fmt.Sprintf("plugins/catalog/%s/%s", pluginType, pluginName)) | 	req := logical.TestRequest(t, logical.UpdateOperation, fmt.Sprintf("plugins/catalog/%s/%s", pluginType, pluginName)) | ||||||
| 	req.Data = map[string]interface{}{ | 	req.Data = map[string]interface{}{ | ||||||
| 		"name":    pluginName, |  | ||||||
| 		"command": pluginName, | 		"command": pluginName, | ||||||
| 		"sha256":  sha, | 		"sha256":  sha, | ||||||
| 		"version": version, | 		"version": version, | ||||||
| @@ -523,7 +596,7 @@ func registerPlugin(t *testing.T, sys *SystemBackend, pluginName, pluginType, ve | |||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	if resp.Error() != nil { | 	if resp.Error() != nil { | ||||||
| 		t.Fatalf("%#v", resp) | 		t.Fatal(resp.Error()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -543,7 +616,7 @@ func mountPlugin(t *testing.T, sys *SystemBackend, pluginName string, pluginType | |||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	if resp.Error() != nil { | 	if resp.Error() != nil { | ||||||
| 		t.Fatalf("%#v", resp) | 		t.Fatal(resp.Error()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -554,6 +627,6 @@ func mountTable(pluginType consts.PluginType) string { | |||||||
| 	case consts.PluginTypeSecrets: | 	case consts.PluginTypeSecrets: | ||||||
| 		return "mounts/foo" | 		return "mounts/foo" | ||||||
| 	default: | 	default: | ||||||
| 		panic("test does not support plugin type yet") | 		panic("test does not support mounting plugin type yet: " + pluginType.String()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -89,7 +89,33 @@ type pluginClient struct { | |||||||
|  |  | ||||||
| func wrapFactoryCheckPerms(core *Core, f logical.Factory) logical.Factory { | func wrapFactoryCheckPerms(core *Core, f logical.Factory) logical.Factory { | ||||||
| 	return func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { | 	return func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { | ||||||
| 		if err := core.CheckPluginPerms(conf.Config["plugin_name"]); err != nil { | 		pluginName := conf.Config["plugin_name"] | ||||||
|  | 		pluginVersion := conf.Config["plugin_version"] | ||||||
|  | 		pluginTypeRaw := conf.Config["plugin_type"] | ||||||
|  | 		pluginType, err := consts.ParsePluginType(pluginTypeRaw) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		pluginDescription := fmt.Sprintf("%s plugin %s", pluginTypeRaw, pluginName) | ||||||
|  | 		if pluginVersion != "" { | ||||||
|  | 			pluginDescription += " version " + pluginVersion | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		plugin, err := core.pluginCatalog.Get(ctx, pluginName, pluginType, pluginVersion) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, fmt.Errorf("failed to find %s in plugin catalog: %w", pluginDescription, err) | ||||||
|  | 		} | ||||||
|  | 		if plugin == nil { | ||||||
|  | 			return nil, fmt.Errorf("failed to find %s in plugin catalog", pluginDescription) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		command, err := filepath.Rel(core.pluginCatalog.directory, plugin.Command) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, fmt.Errorf("failed to compute plugin command: %w", err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := core.CheckPluginPerms(command); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		return f(ctx, conf) | 		return f(ctx, conf) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tom Proctor
					Tom Proctor