This document outlines the OBS ACL feature that has been implemented on the Collabora instance of OBS. This is a feature specific to Collabora OBS only.

Background

OBS currently supports creating multiple projects but it lacks support for a more fine-grained access restriction, for instance to allow certain projects to have a restricted view of other repositories. This support has been implemented by Collabora using ACLs for projects. This document describes the details of the implementation and how to use it.

Use Case

A product team would like to hide all its related OBS projects (e.g. pt:target, pt:development, pt:sdk) from other teams, with only the product team allowed to access these projects.

These instructions are used in the project configuration to hide the projects from others, but the issue is that hidden project cannot be used as a dependency in any other pt:* projects:

<sourceaccess> <disable/> </sourceaccess>  <access> <disable/> </access>

Requirements

Selected OBS projects should be visible only to their project teams:

  • Only explicitly selected people/groups see any information about the selected OBS projects
  • Restricted projects should able to be used as dependencies by other projects without necessarily sharing their sources but still allowing access to the binaries
  • Sources aren’t leaked out to other teams
  • When access is restricted, binaries aren’t leaked out to other teams
  • Published APT repositories for resulting packages are also restricted

OBS ACL Feature Implementation

The OBS ACL feature has the following behaviour:

  • A hidden project is one with <access> set to disabled
  • Build dependencies are via <path project="…" repository="…"/> elements in a <repository> section
  • Any hidden project can use any other hidden project as a build dependency
  • A user who views meta config with a <path …> to a project they cannot see, will see <path project="HIDDEN" …>
  • Said user SHOULD NOT save that meta config but this is not enforced
  • a non-hidden project can still depend on a hidden one, but:
    • the hidden project must whitelist the non-hidden one
    • this is done using the <allowbuilddep name="name:of:public:project"/> element in the meta config
    • this element is contained directly in the <project …> section, i.e. the same level as the <title …>
    • transitive dependencies need to be explicitly listed in the hidden project, unless the special case * glob is used to grant unrestricted usage of the produced binaries by any public project, as in <allowbuilddep name="*"/>

Example demonstration

We have 4 repositories, as listed below:

  • home:user:apertis:demo:base-repo-hidden
  • home:user:apertis:demo:app-repo-hidden
  • home:user:apertis:demo:app-repo-public
  • home:user:apertis:demo:app-repo-allow-build-dep

wherein base-repo-hidden is the base hidden repository, to which no public repositories will have access to by default, unless granted explicit permission.

Then, we have app-repo-hidden repository, which is a hidden repository, and thus will have access to the base-repo-hidden repository.

Next, we have app-repo-public, which is a public repository, and thus will not have access to the base-repo-hidden repository.

And finally, we have app-repo-allow-build-dep, which is also a public repository, and thus would not normally have access to the base-repo-hidden repository, but does via explicit permission in the base-repo-hidden meta config.

home:user:apertis:demo:base-repo-hidden

This is the base OBS repository. This repository houses our private package (in this example, debhelper) which will be used by packages in other repositories as their build dependency.

The configuration of this project is:

<project name="home:ritesh:apertis:demo:base-repo-hidden">
  <title>Base Hidden Repository</title>
  <description/>
  <person userid="ritesh" role="maintainer"/>
  <allowbuilddep name="home:ritesh:apertis:demo:app-repo-allow-build-dep"/>
  <access>
    <disable/>
  </access>
  <repository name="default">
    <arch>x86_64</arch>
    <arch>armv7hl</arch>
    <arch>aarch64</arch>
  </repository>
</project>
Base repository Private overview

Base repository Private overview

As you can see in the image above, the Base Hidden Repository has one package, debhelper, in its repository and it is being built for aarch64 (otherwise known as arm64) and has already succeeded for armv7hl (aka armhf) and x86_64 (aka amd64).

home:user:apertis:demo:app-repo-hidden

This is an example OBS repository which includes an application. This repository is also set as a private repository. Thus this repository will have access to packages from the base repository, which in this case would mean: usrmerge => debhelper. This is because a private repository can access the contents of another private repository.

<project name="home:ritesh:apertis:demo:app-repo-hidden">
  <title>Application Repository Hidden</title>
  <description/>
  <person userid="ritesh" role="maintainer"/>
  <access>
    <disable/>
  </access>
  <repository name="default">
    <path project="home:ritesh:apertis:demo:base-repo-hidden" repository="default"/>
    <arch>x86_64</arch>
    <arch>armv7hl</arch>
    <arch>aarch64</arch>
  </repository>
</project>
App repository Private overview

App repository Private overview

As you can see in the image above, the Application Repository Hidden has one package, usrmerge, in its repository. This package has a build dependency on package debhelper, which is being satisfied from its base repository, home:ritesh:apertis:demo:base-repo-hidden. The package is able to build for all supported architectures.

home:user:apertis:demo:app-repo-public

This is an example OBS repository which includes an application. This repository is also set as a private repository. Thus this repository will have access to packages from the base repository, which in this case would mean usrmerge is unable to satisfy it’s dependency on debhelper. This is because a private repository can access the contents of another private repository.

This repository has the following meta config:

<project name="home:ritesh:apertis:demo:app-repo-public">
  <title>App Repo Public</title>
  <description/>
  <person userid="ritesh" role="maintainer"/>
  <access>
    <enable/>
  </access>
  <repository name="default">
    <path project="home:ritesh:apertis:demo:base-repo-hidden" repository="default"/>
    <arch>x86_64</arch>
    <arch>armv7hl</arch>
    <arch>aarch64</arch>
  </repository>
</project>
App repository Public overview

App repository Public overview

As you can see in the image above, the App Repo Public repository has one package, usrmerge, in its repository. This package has a build dependency on package debhelper, which cannot be satisfied from its base repository because this repository is public. And public repositories do not have access to bits from private repositories, unless explicitly specified. Thus, no build could be triggered in this repository.

home:user:apertis:demo:app-repo-allow-build-dep

This repository is set as public repository, so by default this repository will not have access to packages from the base repository. But, for this repository, we have explicitly added access control into the base repository, allowing it access to packages from the base repository. Thus usrmerge can satisfy it’s dependency on debhelper. As shown in this example, though this repository is a public repository because it is whitelisted in the ACL list of home:user:apertis:demo:base-repo-hidden repository, the package builds properly.

The meta config for this repository is:

<project name="home:ritesh:apertis:demo:app-repo-allow-build-dep">
  <title>App Repo Public with allowbuilddep</title>
  <description/>
  <person userid="ritesh" role="maintainer"/>
  <access>
    <enable/>
  </access>
  <repository name="default">
    <path project="home:ritesh:apertis:demo:base-repo-hidden" repository="default"/>
    <arch>x86_64</arch>
    <arch>armv7hl</arch>
    <arch>aarch64</arch>
  </repository>
</project>

Here’s the meta config for base-repo-hidden, which includes the explicit permission in the form of the <allowbuilddep name="name:of:public:project"/> element

<project name="home:ritesh:apertis:demo:base-repo-hidden">
  <title>Base Hidden Repository</title>
  <description/>
  <person userid="ritesh" role="maintainer"/>
  <allowbuilddep name="home:ritesh:apertis:demo:app-repo-allow-build-dep"/>
  <access>
    <disable/>
  </access>
  <repository name="default">
    <arch>x86_64</arch>
    <arch>armv7hl</arch>
    <arch>aarch64</arch>
  </repository>
</project>
App repository Public (with allowbuilddep) overview

App repository Public (with allowbuilddep) overview

As you can see in the image above, the App Repo Public with allowbuilddep repository has one package, usrmerge, in its repository. This package has a build dependency on package debhelper, which is satisfied from its base repository even though this repository is public. This is because this repository is marked in the allowbuilddep stanza in the home:ritesh:apertis:demo:base-repo-hidden repostiory.

Limitations

There are some limitations in the OBS ACL feature implementation, which are mentioned below:

  • Transitive dependencies are not supported, wherein hidden project A is used by hidden B and the public project C depends on B. In this case, project C needs to be mentioned in every ancestor project, recursively. The <allowbuilddep name="C"> attribute needs to be added to both project A and project B, unless they use <allowbuilddep name="*"> to grant access to every public project, which can be useful in cases where access to sources has to be limited but produced binaries are freely shareable. Incorrect definition of ACL rules, especially like this example of nested rules, results in error messages like the one below:
Broken ACL setup

Broken ACL setup