Is your application compatible with the Affero GPL 3.0 licence?

Products, Uncategorized

I

4–6 minutes

When changing the licence for OneGeo Suite, it is important to review dependency compatibility with the Affero GPL. Given the implications, is it also possible to ensure that our dependencies still have a compliant licence?

Licence compatibility

Licence compatibility includes two key elements to consider:

  • The project itself (e.g., a Python module, a function library, etc.);
  • A derivative work (e.g., a complete piece of software such as Firefox). Derivative works of a project may be modifications to the project’s code or products that incorporate the project.

Licence compatibility is possible when the derivative work has a licence that does not violate the rules of the project’s licence.

“Copyleft” licences require derivative works to be redistributed under the same licence (or a compatible one) to protect the freedoms of the code and the user. Conversely, permissive licences allow relicensing, and it is also possible to create a proprietary product by integrating components under this type of licence. For example, Sony bases the PlayStation’s proprietary operating system on FreeBSD, which is free software under the FreeBSD licence.

Source: https://janelia-flyem.github.io/licenses.html (Creative Commons BY-SA-3.0)

In this diagram, public-domain code can be integrated into an MIT-licensed product, which can itself be integrated into a BSD-licensed product, which can itself be integrated into an Apache 2.0-licensed product, and so on up to the Affero GPL 3 licence.

Two additional categories are introduced by this diagram:

  • Weakly protective: it implies that a modification to the code must be under the same licence (and therefore remain free). However, the project can be integrated into a product under another licence (even proprietary).
  • Network Protective: the GPL protects users of the machine. In client-server applications, the server side protects the server user, i.e., the system administrator. GPL compliance exists when the OneGeo Suite system administrator has access to the modified source code of the product, but the user of the client side does not. Network Protective licences also make it possible to protect the freedom of client users.

Pay close attention to licence versions: for example, the Apache 2.0 licence is compatible with the LGPL licence, whereas version 1.1 is not.

To guide you, here are a few incompatibilities worth highlighting:

  • Apache 1.1 or MPL 1.1 (Mozilla Public Licence) are not compatible with GPL licences, whereas an explicit compatibility clause exists in version 2.0 of those same licences;
  • CC-BY-3.0 prevents changing the licence, so it cannot be changed to AGPL. Version 4.0 explicitly allows changing the licence to GPL 3.0 and therefore to AGPL 3.0;
  • Original BSD licence: it required including a copyright notice in the documentation of the final product, which can be problematic when a product contains many components under this licence.

Check compliance

In practice, licence compliance can be checked using DevOps.

To illustrate our projects, mainly in Python and JavaScript, we present two simple tools that can help you. In these examples, we will use them from the command line to compare dependency licences against an approved list of licences.

Checking licences in Python

The “pylic” tool analyses all Python modules installed in the virtual environment and compares their licences with a section of pyproject.toml. If it finds a module with an unapproved licence, it exits with an error that can be used in CI.

Let us start by installing the program:

$ pip install pylic  

Next, we tell “pylic” which licences are compatible with our software by providing it with a list of AGPL 3.0-compatible licences in the tool.pylic section of our pyproject.toml:

$ cat << EOF >> pyproject.toml 
[tool.pylic]  
safe_licenses = [  
"Apache Software License", 
"BSD License",  
"BSD",   
"MIT License",  
"MIT",   
"Mozilla Public License 2.0 (MPL 2.0)", 
"GNU Library or Lesser General Public License (LGPL)", 
"GNU Lesser General Public License v3 or later (LGPLv3+)",  
  "Python Software Foundation License",  
"Historical Permission Notice and Disclaimer (HPND)"  
  ]  
EOF  

You will notice that these licences sometimes have very similar names. Indeed, “pylic” relies on the name declared by the Python module maintainer (in setup.cfg/setup.py, etc.), which is not standardised. We must declare both identifiers “MIT” and “MIT License” as “safe”, whereas we could have used SPDX licence identifiers in the Python module configuration.

Let us go back to “pylic” and run a check:

$ pylic check  
✨ All licenses ok ✨  

What can be done in the event of non-compliance?

By commenting out the “Apache Software License” entry in pyproject.toml, we get this message:

$ pylic check  
Found unsafe licenses: 
  nltk (3.8.1): Apache Software License  
  phonenumbers (8.13.8): Apache Software License  
  importlib-metadata (6.1.0): Apache Software License
  bleach (6.0.0): Apache Software License  
  cryptography (42.0.1): Apache Software License  
  regex (2023.12.25): Apache Software License 
  django-onegeo-suite (1.0.2): Apache Software License 
  requests (2.31.0): Apache Software License  
  packaging (23.2): Apache Software License 
  pyOpenSSL (24.0.0): Apache Software License 
  tzdata (2023.4): Apache Software License  
  elasticsearch (7.17.9): Apache Software License 
  async-timeout (4.0.3): Apache Software License 
  josepy (1.14.0): Apache Software License  
  django-onegeo-rproxy-mapstore2 (1.0.0b2): Apache Software License  

Quite simple, is it not?

 

Checking licences in JavaScript

Similarly, you can check the licences of JavaScript projects with license-checker. ItIt is still not aware of existing licences, so you will need to build the list manually.

Usage is fairly straightforward:

$ npx license-checker --onlyAllow "CC-BY-4.0;ISC;Apache-2.0;BSD-3-Clause;Custom: https://github.com/tmcw/jsonlint;BSD-2-Clause;Unlicense;UNLICENSED;BSD;Public Domain;CC0-1.0;MPL-2.0" --production   

Package “@fortawesome/fontawesome-common-types@0.2.36” is licensed under “MIT” which is not permitted by the –onlyAllow flag. Exiting. 

You get errors for each unauthorised licence.

The “–onlyAllow” option lists the allowed licences separated by semicolons (“;”). The “–production” option excludes licences for modules in the “devDependencies” section of package.json.

Also remember to correct the “license” section of package.json so as not to confuse the tool:

  "license": "AGPL-3.0-only",  

I also recommend adding a script to package.json to automate the checks:

cat package.json  
{  
[...]  
  "scripts": { 
[...]    "lint": "vue-cli-service lint",  
    "license-checker": "license-checker --onlyAllow \"MIT;CC-BY-4.0;ISC;Apache-2.0;BSD-3-Clause;Custom: https://github.com/tmcw/jsonlint;BSD-2-Clause;Unlicense;UNLICENSED;BSD;Public Domain;CC0-1.0;MPL-2.0\" --production"
  },  

You can then run simply:

$ npm run  license-checker  

 

Conclusion

There are probably more sophisticated tools for checking the licence compatibility of external libraries used by your project, notably by using the OSADL licence compatibility matrix: https://www.osadl.org/html/CompatMatrix.html

However, for a lightweight and quick use in CI, these two tools will do the job, while still investing a bit of time to review any new licences that may appear over the lifetime of your project.

Sources:

https://janelia-flyem.github.io/licenses.html: compatibility image

https://www.gnu.org/licenses/license-list.html: information on GPL compatibility

https://www.apache.org/licenses/GPL-compatibility.html: Apache 2.0 and GPL compatibility

https://medium.com/@iharmandeep/easily-check-licenses-of-your-npm-dependencies-in-your-ci-pipeline-9102150d6907: using license-checker

 

Author: Sébastien DA ROCHA

 

Articles similaires

ProductsUncategorized

OneGeo Chat v2.2: a redesigned interface, smarter conversations

Uncategorized

Tutorial: Effectively Train My First Neural Network

ProductsUncategorized

Your OneGeo Chat chatbot: a technical breakdown