[apparmor] [RFC] Refactoring apparmor-profiles repository

John Johansen john.johansen at canonical.com
Sun Jun 17 23:28:14 UTC 2018


On 06/17/2018 05:56 AM, Vincas Dargis wrote:
> On 6/15/18 8:05 PM, John Johansen wrote:
>> On 06/15/2018 09:36 AM, Vincas Dargis wrote:
>>> On 6/14/18 10:22 PM, Jamie Strandboge wrote:
>>>> Your idea about apparmor/2.13,
>>>> apparmor/2.12 is interesting. I suspect there will be some duplication
>>>> there too, but I'm not terribly about it.
>>>
>>> Yes there will be duplication for the packages that ships updates in stable versions (like Thunderbird and Firefox), while AppArmor abstractions are not being upgraded. That's the main point of basing on AppArmor versions - for clearly defining available abstractions (and their update) and for policy features/versions, that profiles depend heavily on.
>>>
>>
>> So I agree that the repo should be refactored but I am not sure this
>> is the approach that should be taken (possibly for older policy) I
>> need to think about it more. With all policy becoming versioned we are
>> going to see a mixing of different version on the same system. We
>> certainly could segregate on version, making it easier to see what
>> hasn't been updated but then profiles that haven't been updated might
>> get left out and that isn't what we want either.
> 
> With policy versioning we could have single profile for all future AppArmor releases? Basically, no more need to have these directories (nor "ubuntu", neither "apparmor/x.y")?
> 
A possibility, that I would certainly like to get to, but I don't think we will be able to get to it with the 3.0 release

Basically the big issue is installing policy with rules that supports new features on older systems that don't have support for the feature. You could update the userspace but most stable releases are unwilling to do this. To help deal with this in the past we have been front running the features in the parser before they land upstream, but we really need to get away from doing that. We could wrap rules in conditional statements but with the current implementation the parser will break as conditionals are not a preprocess and the rules in their blocks must be parsable.

The long term goal is to allow defining parsing patterns within the parser language itself. So we could add a pattern that would be used to skip/downgrade a rule if the parser doesn't support the feature. So something along the lines of

  if !parser_supports(Xapparmor) {
     ignore pattern 'X' .... # some expression that will let the parser get past the unsupported rule
  }

and eventually if the rules follow supported patterns and don't need anything specially allow declaring the rule patterns in policy entirely.


> Will we have new policy version numbers on every minor AppArmor release (with new/updated abstractions)?
> 
Using policy versioning as a name is really as misnomer, at least at the policy level, the idea certainly started out as such but it has evolved from there.

The idea is that we declare the supported feature abi that the policy was developed under right in the policy it self. This will give a similar effect as using feature pinning but on a per profile basis instead of applying to all policy on the system. If the feature abi is not declared in policy then, policy will fall back to feature pinning and then if there is no declaration the compile will fallback to the 4.14 feature abi as the default.

Policy wise the base of policy versioning is the new feature rule.

  features=<features/file>,

Also instead of sticking the features into a feature file they can be included inline
   features={ blah, blah blah }

the features file will be the same as what is currently used for caching and feature pinning. And in support of this, there will be a couple of additions to the parser language to help identify what is currently supported.

  kernel_supports
  parser_supports
  policy_supports
  supports - asking about what is supported for this compile which is an intersection of what the kernel and the policy supports

hopefully if we do it right we can hide most conditionals within the abstractions.

to abstract some of the details away we are going to wrap the features= rule in an include which will allow us to abstract away anything new we come up with

the include could contain multiple features= rules, defining some variables that can be used conditionally etc.

It is the include file naming and how packaging of policy is handled that would be the closest to what policy versioning implies, and I have been struggling with how best to do this


> Could you give us an example of how versioned profile snippet will look like? Meaning, "if apparmor/policy version is >= X, then include <abstraction/foo>, else copy-pasted rule...".
> 

So I'd like to address the version number first. I would like, if possible, to avoid having to do "if version >= X", I am not saying there won't be cases where something of the sort is needed but I would rather the conditionals be along the lines of

  if (supports(X)) {
     include <abstraction/foo>
  }

and that we keep the conditionals in the abstractions as much as possible

The version abstraction at its most basic would look like
$ cat version/3.0

# feature set supported by the 3.0 release
features=<features/4.17>
# allow policy to also support kernels with the older out of tree patches
features=<features/out_of_tree_net_and_af_unix>
@{version}=3.0    # or perhaps define the var as @{abi} instead doesn't matter as long as we are consistent

$

The idea behind the @{version} variable is then that could be used in policy to do things like

include <abstractions/@{version}/...>

for version specific bits if needed.


a profile file would then do

  include <version/3.0>

to set what its policy version


packaging and dealing with missing bits of policy is where I am failing atm, and 3.0 won't have debhelpers or rpm macros to help with packaging needs around policy versioning.

I am not sure if we want to split the version and feature files into their own packages that packaging can setup dependencies on or whether it should just be dealt with in policy.

policy authors could do things like

  include if exists <version/3.0>

if they want the ability to fallback to a different version, but use a regular include if they want the missing dependency to fail.

I suspect we are going to end up with a mix of packaging and policy magic depending on the policy author needs. Policy that the apparmor project ships could be easily setup to have packaging dependencies but LXD might choose to do something more flexible as they are dynamically generating policy


> Maybe we could still use "apparmor/3.0" directory for new-style versioned profiles, leaving ubuntu/x.y for backpacking as it is now (We will have Ubuntu 18.04 for quite some time). If any day policy changes too much, "apparmor/4.0" could be added, or maybe we are sure enough that that's never going to happen, and we don't need that "3.0" at all?
> 

That is a possibility, and whether or not we are sure that policy will never change enough to require a new version number we are going to keep the option to provide one because if we don't, we will need it later.




More information about the AppArmor mailing list