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

Stronger Microfrontend isolation/sandbox? #215

Open
carvinlo opened this issue May 10, 2020 · 14 comments
Open

Stronger Microfrontend isolation/sandbox? #215

carvinlo opened this issue May 10, 2020 · 14 comments
Labels
enhancement New feature or request help wanted Extra attention is needed in-review The item is currently being reviewed. question Further information is requested
Milestone

Comments

@carvinlo
Copy link
Contributor

New Feature Proposal

For more information, see the CONTRIBUTING guide.

Description

I read your article before, thinking about sandbox isolation. I want to know what you think about the completely isolated sandbox solution, and whether there are other side effects. Such as Qiankun.
What are your thoughts on sandbox and whether they will achieve similar functions in the future, thank you.

Background

[Provide any additional background for the feature, e.g., why is the current solution insufficient, what problem will it solve, etc.]

Discussion

[Optionally, outline any pros and cons you can currently think of to provide the basis for a solid discussion]

@carvinlo carvinlo added the enhancement New feature or request label May 10, 2020
@FlorianRappl
Copy link
Contributor

Unfortunately, it is impossible to create a real sandbox without using <iframe>. Even if you use a proxy (which will cripple the perf + is not supported on older browsers) you'll can easily break out by event delegation or other techniques that eventually give you access to the full spectrum.

Right now this is one of the browser API limitations.

We usually recommend using zoid if stronger guarantees are needed.

I'll leave it open - maybe someone has other good insights or ideas.

@FlorianRappl FlorianRappl added help wanted Extra attention is needed question Further information is requested labels May 10, 2020
@FlorianRappl FlorianRappl changed the title About sandbox Stronger Microfrontend isolation/sandbox? May 10, 2020
@FlorianRappl
Copy link
Contributor

I think we can also introduce an optional iframe for stronger isolation here.

We'll need to do a spike regarding this, but from the top of my head the situation would be as follows:

  1. Certain pilets (or all) will actually not be loaded directly, but via a special kind of proxy function.
  2. The proxy function creates an iframe in which the pilet runs (1 iframe for each proxied pilet).
  3. All registrations are done via messaging, with functions / components being proxied with a special message.
  4. Functions / components are wrapped by the proxy and - once requested / called - rendered / called in the iframe.
  5. We magically place the components from the iframe in the layout. This will be the tricky part.

For this to work the created iframe will have the app shell, too, but running in a special mode that does not load / display the full design, but only bringing the shared dependencies + layout to the pilet.

The advantage of this kind of architecture is that the pilet really does not care if it runs in an iframe or in the full app shell / main frame. It just works. All the proxying / magic is done by Piral.

@FlorianRappl
Copy link
Contributor

Some maybe useful links for getting the components from the iframes embedded seamlessly:

That would, however, require one iframe per component, instead of one iframe per pilet (which may host multiple components).

Are there ways around it?

  1. Host an additional iframe per component (i.e., we have 1 + N iframes per pilet, where N is the number of currently active / shown components): PRO: Quite clean, CON: Super complex (a lot of communication / orchestration needed)
    2.Host a single iframe, which spawns the whole page. but is "transparent" and takes the communication with the parent to determine "placeholders" on the parent. PRO: Somewhat clean, CON: Complex layouting
  2. Host a single iframe, which is hidden and computes all its styles to inline them etc., then essentially moves the components renderings to the parent frame. This is like server-side rendering, just in the browser. PRO: Clean. CON: Not very efficient.

We'll need to do more thinking here.

@carvinlo
Copy link
Contributor Author

carvinlo commented Oct 26, 2020

  1. Host a single iframe, which is hidden and computes all its styles to inline them etc., then essentially moves the components renderings to the parent frame. This is like server-side rendering, just in the browser. PRO: Clean. CON: Not very efficient.

Can this solve:

  • View size, such as maximize the mask layer of modal dialogs

If the pilet is running in an iframe, do we still need to deal with real-time synchronization of the environment (such as real-time synchronization of cookies) ? Or need to resolve the browser’s security restrictions on iframes? (such as https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery)

@FlorianRappl
Copy link
Contributor

What do you mean with "synchronization of cookies"?

The iframes would be created using srcdoc, however, the pilet's script inside the iframe would still come from whereever the script source is. So in some sense it would be identical to the current solution, however, it would be isolated in the sense that the script cannot manipulate the app shell. All interaction would go via the messaging mechanism involving a Pilet API proxy. No other things can be proxied (e.g., manipulation of window).

@carvinlo
Copy link
Contributor Author

What do you mean with "synchronization of cookies"?

All requests inside pilet require to carry the token (stored in cookie) after login. If this problem should not exist in non-cross-domain scenarios, please ignore.

The iframes would be created using srcdoc

Will not produce cross-domain, great.

@FlorianRappl FlorianRappl added the in-review The item is currently being reviewed. label Dec 10, 2020
@FlorianRappl FlorianRappl added this to the 2.0.0 milestone Dec 12, 2020
@gregra81
Copy link

@FlorianRappl Is the iframe suggestion is something you're still pursuing?

@FlorianRappl
Copy link
Contributor

Yes definitely. It's planned for next year.

@carvinlo
Copy link
Contributor Author

This is a framework for sandbox isolation through iframe: alibabacloud-alfa
The article: Sandbox implementation of Alibaba Cloud open platform micro front-end solution

@FlorianRappl
Copy link
Contributor

Thanks for the link @carvinlo - unfortunately, besides just having an iframe it does not solve any of the technical challenges we would face. We potentially render multiple things and need to dynamically place these at the right locations. We also need to dispatch functions (or their results) through a stringified asynchronous pipe.

Again, our idea here would be to discard the internal implementation details for the pilet developer. Only the app shell developers would determine which pilet (if any) will / should be sandboxed.

@alexogar
Copy link

You can consider creating iframe just to do eval of module and dependencies and then return object from iframe to top. This would solve side-effects and versions incompatibility of dependencies and separatelly full isolation in standard iframe

@FlorianRappl
Copy link
Contributor

Hi @alexogar you cannot do that. Only simple (JSON) objects can be transferred, and a function cannot be transported.

Let's pretend for a second that they could... you would have a completely different context in the other frame, so you cannot just render something from there. Rendering from the iframe has to be made inside the iframe. And then we are back to the layouting / synchronization issues described earlier here.

So the story is not as simple as you might think it is.

@alexogar
Copy link

Basically you use iframe only to load JS so it does not interfere with side effects on others (e.g. webpack3 and webpack4 components) multiple versions of ag-grid and other examples. After it is evaluated in iframe you call function from top/parent window to register ready object (plugin/piral) and be rendered in main window.

We use that technique in our internal microfrontend framework. Idea is - you create an iframe with content of js you loaded + you add a function there which can be called by loaded js (e.g. register()) which will call window.parent function to register itself passing your component/piral there. Then it could be rendered using parent react-dom in parent window for example. I'm new to Piral project (found this project yesterday, and very exited ) and will`ll try to look around and craft small PR illustrating that, if I fail to do it here will do sample repo with that technique

@FlorianRappl
Copy link
Contributor

Yeah that would be superb - thanks @alexogar ! Let me know how it goes - would be very cool to drive that forward! 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed in-review The item is currently being reviewed. question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants