Function remains accessible despite internal modifier when service binding allow pattern is permissive
0 reputation · 07 Jul 2023, 01:56 UTC
0 reputation · 07 Jul 2023, 01:56 UTC
When developing a Ballerina service, I want to guarantee that certain helper functions are not callable from outside the defining package, even if the service is bound to an HTTP listener with a permissive allow pattern.
The language provides the private keyword for function‑level visibility and the internal modifier (since 2.2.0) for package‑level visibility. However, it is unclear whether these modifiers interact with service binding allow patterns: does marking a function as internal or private automatically prevent external HTTP invocation when the listener’s allow rule accepts all paths?
Specifically, I need to know if an internal function remains reachable via the service endpoint despite its visibility restriction, and what additional steps—if any—are required to fully block accidental public access.
Does an internal or private function stay inaccessible when the service binding uses an allow pattern of "**"? If not, what configuration (e.g., explicit deny rules or listener‑level security) is needed to enforce the intended access boundary?
An internal or private function in Ballerina cannot be invoked through an HTTP listener solely because the listener’s allow pattern is permissive. The function is only reachable if it is explicitly exposed as an HTTP resource (via @http:Service annotation or as a resource method inside a service object).
Language‑level visibility modifiers (internal, private) control which other Ballerina code can call the function. They do not participate in the HTTP routing mechanism, which inspects only functions/methods annotated for HTTP exposure.
If you observe the helper being reachable despite having no HTTP annotation, check whether the function is being returned or passed as a callable object to the service or listener code, as that can indirectly expose it.
Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 07 Jul 2023, 08:48 UTC
To build on the previous answer, it is important to distinguish between compile-time visibility and runtime dispatch. The internal and private modifiers are enforced by the compiler to prevent other Ballerina packages from referencing those functions in code; they are not security mechanisms for the HTTP runtime.
The HTTP listener does not scan the package for all available functions to map them to URLs. It only registers resource functions defined within a service block. Because a helper function—regardless of its visibility modifier—is not a resource, it never enters the routing table. Consequently, a permissive allow: "**" pattern has no effect on it because there is no route to match.
For those using Ballerina Swan Lake, the most effective way to verify this boundary is to audit the service definitions. If a function is not explicitly declared as a resource, it is unreachable via HTTP, ensuring that your internal logic remains isolated from the network layer.