Powerful, file-based configuration in Magnolia
Jun 2, 2021
--
Powerful file-based configuration 656x400

Powerful, file-based configuration in Magnolia

Magnolia in just 12 minutes

Why not learn more about what Magnolia can do while you have a coffee?

Watch now

The configuration of Magnolia in Light Modules via YAML is an extremely handy feature that we started shipping with Magnolia 6.1. It's been quite a few months since I first used it, but I still remember getting excited when I realized its potential, and I am eager to showcase it here.

Besides configuring dialogs and templates, you can now also change some of Magnolia's core functionality using YAML. The benefit of this low-code approach is a faster implementation of configuration changes without having to deploy a Java module.

In this blog, I will show examples of the configuration of two new Magnolia features using YAML:

  • Cross-Origin Resource Sharing (CORS)

  • Single Sign-On (SSO)

CORS configuration

One common requirement in headless projects is CORS, but did you know that you can configure CORS faster than ever using Light Development?

While not explicitly mentioned in our documentation, it is possible to configure CORS through YAML decoration in a Light Module.

These are the prerequisites that can be configured by following the documentation for REST endpoints and CORS:

  • A REST endpoint: For this demonstration

  • I will use the status endpoint.

  • The site-aware CORS filter: This is the default. To be sure

  • check /server/filters/cors.

  • A CORS configuration for your site

  • for example /modules/multisite/config/sites/<YOUR_SITE>/cors/<YOUR_SITE_CORS_NAME>

Please note that Magnolia offers two options of Magnolia DX Core - with and without our travel demo. I used Magnolia DX Core without the travel demo because the demo’s configuration of the fallback site would interfere with the example.

Since a configuration node now exists, you can use definition decoration from the scope of the Light Module to extend it.

Create the following file:

modules/<YOUR_LIGHT_MODULE>/decorations/multisite/config.yaml.

Now configure CORS as per the documentation and allow requests from localhost:8080:

Java
  sites:
  fallback:
    cors:
      fallback:
        uris:
          rest:
            patternString: /.rest/*
        allowedOrigins:
          - http://localhost:8080
        allowedMethods:
          - GET
        allowedHeaders:
          - Accept
          - Content-Type
          - Origin
          - X-PINGOTHER
          - X-Requested-With

The security settings are now applied to the endpoint, changing its response to an unauthorized origin. You can verify the result using the following command:

Java
  curl 'http://localhost:8080/.rest/status' -H "Origin: http://localhost:8081" -v -o /dev/null  

You should see a 403 error code:

Java
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /.rest/status HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Origin: http://localhost:8081
>
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0< HTTP/1.1 403
< Set-Cookie: JSESSIONID=06AC2693F1AB32108B6CF6E1EA8C6551; Path=/; HttpOnly
< Pragma: no-cache
< Cache-Control: no-cache, no-store, must-revalidate, max-age=0
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< WWW-Authenticate: FormBased
< Content-Type: text/html;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 31 May 2021 08:10:05 GMT
<
{ [1386 bytes data]
100  1379    0  1379    0     0    478      0 --:--:--  0:00:02 --:--:--   478
* Connection #0 to host localhost left intact
* Closing connection 0

This configuration approach has the following benefits over the standard configuration:

  • It is independent from the instance's configuration

  • and you do not have to write it to JCR using a Java module.

  • Updating this configuration is much easier. Just update the file for Magnolia to implement the change immediately.

  • It is stored in a plain text file that can easily be added to a Git repository with all its benefits.

Low-code Development

Simplify and speed up development with Magnolia using file-based configuration.

SSO configuration

The new pac4j-based Magnolia SSO module also uses YAML decoration, simplifying the complex integration with authentication services as much as possible.

A word of caution: When you install the module, we assume you'll want to use it, and the module will attempt to take control of your instance. We recommend installing the module in a development environment before rolling it out to production, but I assume that this is already an established good practice.

The initial configuration file is empty, waiting to be decorated. Once the configuration is tuned, Magnolia will implement any changes instantly.

This is the first half of the configuration file

<MODULE_NAME>/decorations/magnolia-sso/config.yaml:

Java
  authenticationService:
  path: /.magnolia/admincentral
  callbackUrl: http://localhost:8080/.auth
  groupMappings:
    /magnolia-sre:
      roles:
        - superuser

This configuration:

  • Delegates authentication for your instance's AdminCentral to a third-party identity provider

  • Asks the identity provider to redirect to callbackUrl when a user has been logged in

  • Applies groupMappings to the user's groups property to grant access to AdminCentral

Integration with pac4j's file-based configuration

I'm very eager to share a great improvement in the latest version of the module: it integrates with pac4j's YAML configuration. This means that the module is compatible with any OpenID Connect identity provider.

We’ve validated the use case with Keycloak and Okta. This is the configuration we've used to describe the client's OpenId Connect properties for pac4j to assess incoming requests from the identity provider.

Java
  authenticationService:
  pac4j:
    oidc.id: magnolia-sso
    oidc.secret: 2ff75b44-c7ef-4932-91c8-59e6ea5f35b6
    oidc.scope: openid profile email
    oidc.discoveryUri: https://<YOUR_OIDC_IDP_DOMAIN>/…/.well-known/openid-configuration
    oidc.preferredJwsAlgorithm: RS256

This is what the entire configuration file looks like:

Java
  authenticationService:
  path: /.magnolia/admincentral
  callbackUrl: http://localhost:8080/.auth
  groupMappings:
    /magnolia-sre:
      roles:
        - superuser
  pac4j:
    oidc.id: magnolia-sso
    oidc.secret: 2ff75b44-c7ef-4932-91c8-59e6ea5f35b6
    oidc.scope: openid profile email
    oidc.discoveryUri: https://<YOUR_OIDC_IDP_DOMAIN>/…/.well-known/openid-configuration
    oidc.preferredJwsAlgorithm: RS256

Conclusion

I hope this article was helpful in explaining definition decoration. It’s an auxiliary mechanism that is explained in later sections of our documentation and often considered in later stages of a project. There’s a bit of overhead for the setup, but I hope I have convinced you that the benefits are well worth the effort.

If you need help getting this implemented, you can send me an email.

About the author

Maxime Michel

Site Reliability Engineer, Magnolia

Half developer, half Site Reliability Engineer (SRE), Maxime contributes to Magnolia’s source code and works closely with the wider product development team. He believes that machines can take care of repetitive tasks so that people can focus on more creative and interesting work. In his role at Magnolia, Maxime is responsible for processes and automation to present our users with a simple solution and a great user experience.