Skip to content
Toparvion edited this page May 16, 2019 · 1 revision

Log Access Control

Overview

AnaLog can restrict access to certain logs to prevent sensitive data from leaking (e.g. queries like GET http://analog-host/etc/passwd).

ℹ️ As of v0.12 the restriction is provided for file logs only (both remote and local ones).

To manage access restrictions the administrator can use allowed-log-locations top-level configuration section of application.yaml file. The file subsection can be used to specify allowed file log locations (and exceptions from them) in the form of Glob path patterns.

AnaLog ships with the following default access configuration:

allowed-log-locations:
  file:
    include:
      - ${user.home}/**.log
      - ${user.dir}/**.log
    exclude:
      - ${user.home}/**/.**
    symlink-resolution-limit: 1

It allows reading of non-hidden logs from current user’s home directory tree as well as reading any logs from AnaLog’s own working directory tree.

The following section describes the restriction mechanics in detail.

Details

AnaLog performs access check in the following cases:

  • On every start of a new file log tailing process.
    It means that if a client just subscribes to an existing tailing process, no access check is performed.

  • On certain file tailing events.
    It provides additional defense against path manipulating after initial checking.

  • On downloading of a file log.

The checks are performed on the current instance’s agent side, i.e. every AnaLog instance controls its own logs only and doesn’t restrict others in any way. As a result, there is currently no way for the administrator to declare all the access configuration on single instance (“master”) and make it come to effect everywhere.

The access control procedure consists of the following steps.

1. Checking if file log access is denied at all

AnaLog uses restrictive access model, i.e. everything that is not explicitly allowed, is denied. Therefore there must be at least one entry in allowed-log-locations.file.include list to read any file log. Otherwise AnaLog totally denies file log access and immediately returns the following message to the client:

No allowed file log locations specified. See 'allowed-log-locations' property.

This can be useful for AnaLog instances that are not intended for working with file logs (e.g. if they are meant to work with container logs only).

2. Normalizing the path

On this step AnaLog:

  1. converts all the slashes of the path to current OS format

  2. turns the path to an absolute one without any relative parts (i.e. gets rid of parts like ../some-dir/..)

  3. resolves symbolic links as many times as allowed-log-locations.file.symlink-resolution-limitproperty specifies. In case of violation AnaLog prevents log from reading and returns the following message to client:

    Symbolic links resolution limit (<limit-value>) has been reached.
    

    If the property equals 0, symlink resolution is denied at all (logs cannot be read through links) and the client receives the following message:

    Symbolic links to logs are not allowed.
    

These three steps provide subsequent checking with actual log paths rather than various pointers like relative paths, symlinks, etc.

3. Checking the path against including patterns

On this step AnaLog checks normalized path against allowed-log-locations.file.include config section which contains a list of Glob patterns.

ℹ️ Simply put, Glob patterns lets you specify a path either as usual e.g. /home/me/app.log or in a more generic way e.g. /home/me/*.log. The last means “give me all files that reside in /home/me directory and whose names end with .log

The requested log path must match at least one of the patterns to pass the check. AnaLog processes the list from top to bottom, the first matching pattern wins, no other patterns are examined in this case. If no patterns are specified, an error is returned immediately (see first check above).

When no matching patterns are found, the log is denied from reading and the following message is returned to the client:

Access denied: Path '<path>' is not included into 'allowed-log-locations' property.

Note that matching to any of including patterns is not sufficient for a log to be allowed for reading because AnaLog also checks every log path against excluding patterns (see next).

4. Checking the path against excluding patterns

On this step AnaLog checks given path against allowed-log-locations.file.exclude config section which also contains a list of Glob patterns.

The requested log path must not match any of the patterns to be allowed for reading. AnaLog processes the list from top to bottom, the first matching pattern wins, no other patterns are examined in this case. If no excluding patterns are specified, the path is considered allowed for reading.

When matching pattern is found, the log is denied for reading and the following message is returned to the client:

Access denied: Path '<path>' is excluded from 'allowed-log-locations' property.

Excluding patterns are meant to somehow narrow the including patterns. They also can serve as exceptions from the implicit list of logs matching the including patterns. To understand it better, you can formulate the access control logic as the following sentence:

I want my logs to be allowed for reading from (<inclusion1> or <inclusion2> or …) but not from (<exclusion1> and <exclusion2> and …)

Note that including patterns (<inclusion>) are combined with or while excluding patterns (<exclusion>) are combined with and.


Variables substitution

You can refer to various external values from within access settings with the help of ${...} notation. The values can originate from:

  • OS environment variables
  • AnaLog’s JVM properties (both system and user-supplied)
  • neighbor parameters

For example:

allowed-log-locations:
  file:
    include:
      - ${user.home}/**.log        # JVM built-in property (current OS user home dir)
      - ${JAVA_HOME}/lib/classlist # OS environmental variable
      - **/${nodes.this.name} 	   # locally defined parameter (AnaLog's current node name)
    exclude:
      - **/${user.name}.log        # JVM system property (current OS user name)