TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Firewalling your code

124 点作者 tie-in9 个月前

29 条评论

mightybyte9 个月前
I think the general concept here is putting in place restrictions on what code can do in service of making software more reliable and maintainable. The analogy I like to use is construction. If buildings were built like software, you'd see things like a light switch in the penthouse accidentally flushing a toilet in the basement. Bugs like that don't typically happen in construction because the laws of physics impose serious limitations on how physical objects can interact with each other. The best tools I have found to create meaningful limitations on code are a modern strong static type system with type inference and pure functions...i.e. being able to delineate which functions have side effects and which don't. These two features combine nicely to allow you to create systems where the type system gives you fine-grained control over the type of side effects that you allow. It's really powerful and allows the enforcement of all kinds of useful code invariants.
评论 #41369153 未加载
评论 #41368666 未加载
评论 #41367969 未加载
评论 #41367294 未加载
eithed9 个月前
We&#x27;re using similar approach in PHP application by facilitating <a href="https:&#x2F;&#x2F;github.com&#x2F;spaze&#x2F;phpstan-disallowed-calls">https:&#x2F;&#x2F;github.com&#x2F;spaze&#x2F;phpstan-disallowed-calls</a><p>In essence we have defined within each domain: a) Public folder with code that other domains can use b) domain folders (src and infra) with code that only given domain can use. This way developers know not to change public contracts for a (or if they do change them they do understand they&#x27;re changing public code) be it method signatures or interfaces and are free to refactor b, because these classes should not be publicly accessible and can change at any time. Even extending classes defined this way is disallowed.<p>This becomes helpful when operating within confines of monolith application, but with different teams owning different parts of the application. Trying to use non-public part of each domain will be prevented on commit level (developers will not be able to commit their work) rather than run level though
评论 #41366572 未加载
wokwokwok9 个月前
It’s probably over the top, although I respect the intent.<p>The quickest way to destroy “velocity” is by introducing dependencies between implementation details with no barriers in code.<p>The more constraints you have to satisfy when you make changes, the more effort it is to make the changes (provably); and thus, the more time it takes, destroying velocity.<p>That said, doing this as described is probably overly dramatic; I like the rust model: by default, parents can access child scopes, and children can access their immediate parent. Otherwise you have to explicitly “pub” a symbol <i>even to use it in the same crate</i>, which is the escape hatch for pragmatism over strictness.<p>It would be lovely if some other languages (js, python) had such a delightful module system, but, they don’t.<p>With something as fundamentally undisciplined (“flexible”) as js, you need to enforce the rules pragmatically with process and tools like code reviews and linking.<p>It is worth doing though; this is one of my favourite architectural topics because it’s so easy to totally destroy anyone who tries to argue the point. :)
评论 #41366590 未加载
评论 #41376345 未加载
评论 #41367207 未加载
asmor9 个月前
Always feels like you&#x27;re in a dysfunctional place when you have to program this defensively.<p>I had an acquaintance who was writing library code for a few dozen data engineers in python, and she had to resort to locking down private methods by checking the call stack after engineers repeatedly got hold of private objects, or objects that are only there sometimes (e.g. when not running clustered).<p>I adopted a similar stance of &quot;you can&#x27;t abuse what you can&#x27;t access&quot; in platform engineering too, but I am not the greatest fan of having to do this in the first place. But the alternative always seems to be that someone will change the scope of what&#x27;s supported by you for you, as soon as someone builds a dependency.
评论 #41367336 未加载
评论 #41366119 未加载
评论 #41366682 未加载
评论 #41366171 未加载
ChrisMarshallNY9 个月前
I&#x27;ve worked like this for decades.<p>Layers, with each layer assigned a particular domain and API restriction (for example, I have a multi-layer backend, and, if I want to access the database directly, I need to implement that at the very lowest layer, and then set up a &quot;tunnel&quot; of access to the top-layer exposed API, through the intervening layers, applying whatever access control and filters are appropriate for each layer).<p>C++, if I remember correctly, had a lot of attributes you could assign to classes and types, to regulate access, but it&#x27;s probably been around 20 years, since I&#x27;ve written C++.
评论 #41366551 未加载
评论 #41367594 未加载
评论 #41371050 未加载
Rhapso9 个月前
For compiled languages, bazel has &quot;visibility&quot; which enables this <a href="https:&#x2F;&#x2F;bazel.build&#x2F;concepts&#x2F;visibility" rel="nofollow">https:&#x2F;&#x2F;bazel.build&#x2F;concepts&#x2F;visibility</a>
skilning9 个月前
This concept has been around for ages. I remember way back in a previous life as a Java dev having a framework where you could annotate methods with permission requirements, and the framework would add runtime instrumentation to ensure the proper context was created in the current thread and had the proper permissions to invoke that method any time it was called.
quectophoton9 个月前
Sounds similar to capabilities: <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Capability-based_security" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Capability-based_security</a>
评论 #41367442 未加载
评论 #41367187 未加载
评论 #41367276 未加载
iainmerrick9 个月前
<i>How can you ensure that the modules follow these rules?</i> [...] <i>As a proof of concept, I’ve created a Node.js library called firewall-js using JavaScript proxies.</i><p>Unless I misunderstand, there&#x27;s a vastly simpler way to do this:<p>- use a monorepo;<p>- put each module in its own package.
jonathanlydall9 个月前
This seems pretty neat for when your layer separation is merely by folders in JavaScript.<p>It&#x27;s unfortunate that this doesn&#x27;t highlight any problems until the code is run as I feel it&#x27;s always best to find out as soon as possible you&#x27;re making a mistake, your IDE instantly telling you of a problem as you try write the code is the most ideal time, with the next being compilation. In this case probably even a simple integration test would instantly let you know, which isn&#x27;t terrible.<p>There is a run time performance impact too here, but I would expect its cost is reasonable for the value it adds.<p>In the C# space (and I imagine many other languages have equivalent options), layer segregation is a good reason to split your code into multiple assemblies (or projects) and the compiler can then enforce the layering. Of course we sometimes also split things up to into different assemblies for other reasons too, but for any non-trivial sized code base, I consider that one assembly per layer is the bare minimum.
评论 #41366900 未加载
matsemann9 个月前
This is basically what java modules do, right? From java 9 and onwards.<p>You have public stuff within your module, that other packages in the module can use. But another module cannot use it without you declaring it as part of your actual public facing API. I don&#x27;t see people use it much in application code, though. Often just a single module where people can call everything.
评论 #41367104 未加载
jFriedensreich9 个月前
it seems like a good direction but wrong layer of abstraction. have a look at cloudflares workerd architecture with nanoservices and capability based permissions. you can build all this on a runtime level where services are not even allowed to access the internet or any file except for explicitly configured bindings. these bindings can contain logic too so an egress service could also contain logic for filtering or rewriting etc. this is so powerful and still underhyped
KingOfCoders9 个月前
Neglected topic IMHO don&#x27;t trust other parts of your code base. I wrote about how to firewall your code with Casbin in in Go<p><a href="https:&#x2F;&#x2F;www.inkmi.com&#x2F;blog&#x2F;simple-example-casbin-rbac-abac-ownership-golang" rel="nofollow">https:&#x2F;&#x2F;www.inkmi.com&#x2F;blog&#x2F;simple-example-casbin-rbac-abac-o...</a>
aljarry9 个月前
There are libraries for writing Architecture tests for .Net and java (that I know of) for enforcing architecture design. You can enforce reference rules for classes and namespaces, like: classes from the domain namespace cannot reference the API or DB namespaces.<p>I haven&#x27;t used them in a real project though.
ludovicianul9 个月前
This is why I like to use <a href="https:&#x2F;&#x2F;www.archunit.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.archunit.org&#x2F;</a> in my Java apps. It allows you to test how the application is structured and being unit tests, they will verify that with every build.
notpushkin9 个月前
Slightly tangential, but I&#x27;ve found importlinter neat for restricting what layers in your Python code can call each other (in this case by restricting <i>imports</i>, not calls): <a href="https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;import-linter&#x2F;" rel="nofollow">https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;import-linter&#x2F;</a><p>For example, you can ensure lower-level packages don&#x27;t import higher-level ones:<p><pre><code> [importlinter:contract:my-layers-contract] name = Layered architecture type = layers layers = mypackage.cli # can import anything mypackage.services # can&#x27;t import from mypackage.cli mypackage.models # can&#x27;t import from .cli or .services</code></pre>
hprotagonist9 个月前
Reminds me somewhat of capabilities: <a href="http:&#x2F;&#x2F;habitatchronicles.com&#x2F;2017&#x2F;05&#x2F;what-are-capabilities&#x2F;" rel="nofollow">http:&#x2F;&#x2F;habitatchronicles.com&#x2F;2017&#x2F;05&#x2F;what-are-capabilities&#x2F;</a>
lloydatkinson9 个月前
That `userService` example is just awful, it feels like it&#x27;s trying to achieve so many things with exactly the worst options.<p>- Not using ES modules which is compounded by: - Creating a random &quot;bag of crap&quot; as I call it by throwing all the functions into an exported object - Can&#x27;t even get static build time feedback about the functions you&#x27;re calling or if they even eixst which you would if:<p>The better alternatives here are:<p>- Just have plain exported *functions* in an ES module - If you need shared state both functions access then export a plain class in an ES module
tommica9 个月前
What an curious approach - seems like it would be a mess to maintain in a larger project, but the concept of controlling who&#x2F;what can call the public functions is an interesting idea.
评论 #41367223 未加载
hartror9 个月前
I would think Lint rules are better for encouraging this and has no run time implications. Easy escape hatches as well if you really want to crack the firewall to ship something urgently.
jmclnx9 个月前
Looks kind of like OpenBSD&#x27;s pledge(2) and unveil(2).<p>I have used both and I personally think those calls are the best security mitigations in our field :)<p>I would love to see something as simple in Linux.
vanjajaja19 个月前
I like the idea but I think its in the wrong place.<p>They&#x27;re kind of like contract statements for preconditions&#x2F;invariants but at the design layer, enforced at compile &#x2F; run time.<p>I think this is useful for architect types, though I think this belongs more around the DependencyInjection config area.<p>A class should not be aware of what uses it.
layer89 个月前
IMO the better way to handle this is to statically determine the Dependency Structure Matrix of all modules and to have a linter in the build process that checks that the dependencies conform to the restrictions you want to impose.
JonChesterfield9 个月前
The idea (as I understand it...) is to structure the codebase as a directory tree and have position in the tree determine whether some module can call into another or not. Something along the lines of a function can call into one defined in source at the same level or below, but not above.<p>I did that for a while in C. It does sort of work. Layout amounted to:<p><pre><code> foobar.h foobar&#x2F;foobar.c foobar&#x2F;misc.h foobar&#x2F;misc.c foobar&#x2F;submod.h foobar&#x2F;submod&#x2F;submod.h foobar&#x2F;submod&#x2F;other.c </code></pre> The scheme there was #include to get at peer or submodule source, where not using &quot;..&#x2F;&quot; in the path avoided trying to access parent modules.<p>Within a simple header&#x2F;source pair make the declared functions global and all the others static. For the header&#x2F;directory pair, compile the source files, link them, internalise the symbols that aren&#x27;t external in the file with the name matching the directory.<p>I still broadly like that approach. The llvm-link &amp;&amp; internalise applied at submodule scope has the side effect of optimising the modules individually. You can start with a header&#x2F;source pair and convert it to a header&#x2F;submodule pair without disturbing the rest of the codebase.<p>What doesn&#x27;t work so well, and also isn&#x27;t addressed in the &quot;firewalling&quot; post, is that inevitably the dependency tree wants to pick up a cycle. Some dependency of some module looks like it would be useful to another module and include &quot;..&#x2F;..&#x2F;foobar&#x2F;misc.h&quot; suddenly appears in the scheme and promptly fails to link because misc.c&#x27;s symbols are hidden inside foobar.<p>The &quot;fix&quot; is either to abandon this scheme, start putting functions as static inline in header files as a &quot;temporary&quot; workaround, or to move the multiply-used dependency up through the tree until it is accessible to everything that wants it. &quot;Misc&quot; is prone to ending up at the top level.<p>I think that pattern died when I disabled the internalise step to help debug something where I wanted to pull in code from elsewhere and then never re-enabled the internalisation. It still seems like a broadly good idea but it does shine a clear light on the dependency structure of the codebase which obstructs the natural descent into a ball of mud. These days I think I&#x27;d want the internalise &#x2F; strict separation enforced in CI builds and not in dev builds (much like unused variables and similar).<p>Nice to be reminded of that pattern. Thanks for posting the site.
Goofy_Coyote9 个月前
How is this different from using access modifiers (public, private, protected)?<p>P.S: I do work with code (reading, writing and breaking it), but I’m not a software engineer.
评论 #41367966 未加载
cheschire9 个月前
Alternate title: How to terrorize codebase maintainers 5 years after your departure.<p>Maybe one step further would be to leverage a lot of encrypted stored procedures in SQL.
macspoofing9 个月前
So.. JavaScript is slowly reinventing OO class and module access controls?
ugizashinje9 个月前
sounds like ABAC on service level, go check <a href="https:&#x2F;&#x2F;casl.js.org&#x2F;v6&#x2F;en&#x2F;" rel="nofollow">https:&#x2F;&#x2F;casl.js.org&#x2F;v6&#x2F;en&#x2F;</a>
xnorswap9 个月前
So now when you want to use a dependency, you have to update that dependency?<p>Isn&#x27;t that a maintenance headache which doesn&#x27;t really stop people doing that anyway?<p>I understand the desire for this, having long and messy dependency chains can completely grind large changes to a halt. I&#x27;m currently dealing with a .net solution of ~300 projects with a dependency tree that&#x27;s better described as a dependency web.<p>But this feels like the wrong solution. Better isolation can be achieved by proper packaging and leveraging of private package repositories.