Before I even started with Elixir I had an idea to create project like that, but with some experience now I have much more cleaner idea. I would like to ask community if some things are possible in Elixir and what API or libraries could help me with that.
Project targets:
Any application/library could be also plug-in for my application, but it needs to add some code
Any plug-in should not affect other plug-ins and main application
My app should have a public allowed API that plug-in can use
Any plug-in could ask for permission to add itās own public API for other plug-ins
Any plug-in should not directly work on database. Instead of it should:
a) got (by main app API) an PostgreSQL schema that it will work on (to not conflict between models)
b) ask for permission for each other schema to read data
c) ask for permission for each other schema to write data
From targets what I need to is:
Write a module that manages plug-ins:
a) download from hex
b) read mix.exs file and search for plugin_prepare alias
c) run mix deps.get + tasks from plugin_prepare alias + mix test - check if all finishes without error - here I also need run migration with main application repo ā¦
Write permission API for:
a) modules
b) ask plug-in modules
c) read and write to other schemas
First point not looks really hard, but second is much more harder:
How I can run callback: &Module.function/args_count from another project (here: plug-in)
I want to add plug-ins dynamically, so manually adding them to deps in mix.exs is not what Iām looking for.
When running callback from point 1 how to add List of modules to that project? For example:
defmodule HexName.Plugin.ModuleCallbackName do
def callback_method_name do
# firstly I need to add MainApp.PermissionManager here:
allowed_apis = MainApp.PermissionManager.list
# then add all modules from allowed_apis Map
required_api = Match.fetch(allowed_apis, :api_id)
unless required_api == :error do
args = []
apply(required_api, :function_name, args)
end
end
end
Is it even possible to write something like I described in Elixir? Do you know any API/library that could help me with it? Do you know any article that will help me understand how could it work (apply callbacks between projects).
Maybe easier way is to implement something like WebSocket server-client for localhost connections (for communications between main project and plug-ins), but it requires that every project needs to have support for WebSocket ā¦
Can you help me find a safest and easier way to implement it?
Well there are lots of ways to implement such a thing, but I guess it mostly depends on how sandboxed you want them to be, like if by public allowed API then behaviours or whatever are usual, if however by that you mean they should absolutely not be allowed to access anything else at all for security reasons, then use lua or some port program (or you can parse the elixir AST yourself and whitelist what you want, but that would be a pain, EVM languages are very good at introspecting a system)ā¦
So yeah, first question, how sandboxed do you want it?
@OvermindDL1: Thank you for your reply!
I would like to do it in Elixir way whenever itās possible, so I would like to choose: they should absolutely not be allowed to access anything else, but I donāt want to end with something like: type_class
Also parse the elixir AST yourself sounds like black magic for me. If I would decide to do it then I will do it only after some years, because I should increase my knowledge about Elixir and do it well.
So Iām looking for: easier method to safe communicate between two separate Elixir projects rather than parse the elixir AST myself - itās why I think about using WebSocket (or similar) API for it.
Yeah if you want to run code in the same VM then you are in for one of the levels of hell, Iād recommend not doing that. ^.^
If anything Iād say support lua, this sounds like exactly the use-case for it. Or opt for a websocket API if it can be done remotely and it is not time sensitive (all remote network communication will induce a noticable delay), etcā¦
@OvermindDL1: WebSocket is only example - itās technology that I already work with in Elixir language. I mean that main application will start each project as another system process in sandbox and they will be communicating by public API.
I donāt know if lua language is good choice, because I want that any Elixir project could be easily an plug-in for it for my app - so it need just to implement some callbacks like: AppName.Plugin.CallbackModeuleName.
@OvermindDL1: ah, I see - sorry I was focused on main app security rather than sysyem security
How about run each plug-in in something like chroot? I probably hear about something like it, but not remember it so much.
Chrootās are not secure. VMās are not secure. Illumos containers are āsecureā for some definition there-of, but better than the prior. Where would this plugins come from and who would be able to load them?
@OvermindDL1: Only developer/service account and owner account, but keep in mind that owner do not need to know how it works inside.
Developer and owner will probably login only in local network - like 2 root accounts.
Developer account will be like owner account + some more info / options to help debug.
I donāt even hear about Illumos containers. Can you link to a good tutorial about it? Is it possible to have JSON API (like in Phoenix Channels) between main app and that plug-in in Illumos container?
@OvermindDL1:
I donāt found anything named "Illumos containers" directly. I see that Illumos is OS that derives from OpesnSolaris and therefore I found Solaris Containers and if I good understand then Illumos containers are better. I donāt feel bad with learn other distribution/OS, but keep in mind that Linux distributions are more popular in servers, so my solution will be good only for small percent of developers in production environment - itās only why I will not try this, but I will keep in mind what you say and maybe I will personally try them myself in future.
I think again about this topic and found another way that looks not so bad for me.
If we want to be really secure (but without any virtual machine) then how about it:
for each plug-in create an fake (canāt login) Linux account like: __project_name__plugins__plugin_name__ with plugins/plugin_name as home directory.
each plug-in could work on tmp/plugin_socket (relative path) as normal Phoenix application with json API
so if plug-in is a fake then it cannot do anything other that break itself and Iām not reserving all Linux TCP ports for (possibly) millions of plug-ins.
For me this looks like a good balance between security and easy install. What do you think about it?
@DianaOlympos and @OvermindDL1: by security you mean protect distribution/OS right?
I mean protect my project and basic protect for other things for example do not allow delete project files or format partition with my project and plug-ins - itās why I started from my idea. Limited accounts should not affect whole project and other plug-ins. Anyway it looks really interesting and I already found some hosting services that offers this. Thank you!
As in protecting your server code from being subverted by the plugins. Protecting the host OS is also a noble goal, and quite necessary as well or the plugins could use those vectors to attack your server anyway.
Iām just having flashbacks of seeing PHP Forum plugins that completely take-over your web server, whether directly or by leaving an attack vector open that should not have been. ^.^;