Cloud Security Container Integrations

The following containers are integrated with Helidon Security:

Web server

Integration of reactive web server

Maven Dependency
<dependency>
    <groupId>io.helidon.security.integration</groupId>
    <artifactId>helidon-security-integration-webserver</artifactId>
</dependency>
Copied

Bootstrapping

There are two steps to configure security with web server:

  1. Create security instance and register it with server
  2. Protect routes of web server with various security features
Example using builders
// web server's Routing
Routing.builder()
    // This is step 1 - register security instance with web server processing
    // security - instance of security either from config or from a builder
    // securityDefaults - default enforcement for each route that has a security definition
    .register(WebSecurity.create(security).securityDefaults(WebSecurity.authenticate()))
    // this is step 2 - protect a route
    // protect this route with authentication (from defaults) and role "user"
    .get("/service1", WebSecurity.rolesAllowed("user"), (req, res) -> {
        processService1Request(req, res);
    })
    .build();
Copied
Example using configuration
Routing.builder()
    // helper method to load both security and web server security from configuration
    .register(WebSecurity.create(config))
    // continue with web server route configuration
    .build();
Copied
Example using configuration (YAML)
# This may change in the future - to align with web server configuration, once it is supported
security.web-server:
  # Configuration of integration with web server
  defaults:
    # defaults for paths configured in the section below
    authenticate: true
  paths:
    - path: "/service1/[/{*}]"
      methods: ["get"]
      roles-allowed: ["user"]
      # "authenticate: true" is implicit, as it is configured in defaults above
Copied

Note: defaults section in configuration is related to paths on WebServer configured below in paths section, it will not apply to any other path on the webserver.

Protecting Helidon endpoints

There are several endpoints provided by Helidon services, such as:

  • Health endpoint (/health)

  • Metrics endpoint (/metrics)

  • OpenAPI endpoint (/openapi)

  • Configured static content (can use any path configured)

These endpoints are all implemented using Helidon reactive WebServer and as such can be protected only through Security integration with WebServer.

The following section describes configuration of such protection using configuration files, in this case using a yaml file, as it provides a tree structure.

Configuring endpoint protection

The configuration is usually placed under security.web-server (this can be customized in Helidon SE).

The following shows an example we will explain in detail:

application.yaml
security:
  providers:
    - abac: 
    - provider-key: 
  web-server:
    defaults:
      # defaults for paths configured in the section below
      authenticate: true 
    paths:
      - path: "/metrics[/{*}]" 
        roles-allowed: "admin"
        # "authenticate: true" is implicit, as it is configured in defaults above (same for paths below)
      - path: "/health[/{*}]" 
        roles-allowed: "monitor"
      - path: "/openapi[/{*}]" 
        abac:
          scopes: ["openapi"]
      - path: "/static[/{*}]" 
        roles-allowed: ["user", "monitor"]
Copied
  • Attribute based access control provider that checks roles and scopes
  • The provider(s) used in your application, such as oidc
  • Default configuration for paths configured below in paths section
  • Protection of /metrics and all nested paths with admin role required
  • Protection of /health and all nested paths with monitor role required
  • Protection of /openapi and all nested paths with openapi scope required
  • Protection of static content configured on /static path with either user or monitor role required

If you need to use a properties file, such as microprofile-config.properties, you can convert the file by using index based numbers for arrays, such as:

microprofile-config.properties
security.providers.0.abac=
security.providers.1.provider-key.optional=false
security.web-server.defaults.authenticate=true
security.web-server.paths.0.path=/metrics[/{*}]
security.web-server.paths.0.roles-allowed=admin
# ....
security.web-server.paths.3.path=/static[/{*}]
security.web-server.paths.3.roles-allowed=user,monitor
Copied

Jersey

Integration of Jersey (JAX-RS implementation) both for inbound and outbound security.

Maven Dependency
<dependency>
    <groupId>io.helidon.security.integration</groupId>
    <artifactId>helidon-security-integration-jersey</artifactId>
</dependency>
Copied

Inbound security

Integrate with Jersey
ResourceConfig resourceConfig = new ResourceConfig()
    // register JAX-RS resource
    .register(JaxRsResource.class)
    // integrate security
    .register(new io.helidon.security.jersey.SecurityFeature(security));
Copied

Protecting a resource

The current approach does not have a configuration option. The security must be configured through annotations. Security currently supports @Authenticated and @Authorized. When a resource is annotated with one of these annotations (application class, resource class, or resource method), security will be triggered.

Securing a resource method
// this is sufficient for security to be triggered, see javadoc for further details
@Authenticated
@Path("/{name}")
@GET
@Produces(MediaType.TEXT_PLAIN)
// due to Jersey approach to path matching, we need two methods to match both the "root" and "root" + subpaths
public String getHelloName(@PathParam("name") String name) {
    return "Hello " + name + ", your current subject: " + securityContext.getSubject();
}
Copied

Access context

Support in a JAX-RS resource
// inject io.helidon.security.SecurityContext
@Context
private SecurityContext securityContext;
Copied

Outbound security

Outbound security is automatically registered with Jersey client. The provider must have outbound security configured for identity to be propagated.

Maven Dependency
<dependency>
    <groupId>io.helidon.security.integration</groupId>
    <artifactId>helidon-security-integration-jersey-client</artifactId>
</dependency>
Copied
Call remote target with outbound security
Client client = ClientBuilder.newClient();

try {
    // call the resource, will propagate identity as configured in Security
    String response = client.target("http://www.google.com")
        .request()
        // configure the security context for this request (as client and targets may be re-used)
        .property(ClientSecurity.PROPERTY_CONTEXT, securityContext)
        .get(String.class);
} finally {
    client.close();
}
Copied