3.6. Security Setup #

3.6.1. Setting up an Operating System User #

pgpro-otel-collector can be run by an unprivileged user. In some cases, however, read access to the log directory and log files may be required on the operating system side for collecting logs from the DBMS instance.

3.6.1.1. Setting up Read Access to DBMS Logs #

To read the logs, it is sufficient to use the group under which the DBMS instance is running. To do this, the group needs to be granted read access to log files, and then the user under which the collector is running should be added to the same group. Typically, this is the postgres group.

  1. Grant read permissions to the group (the directory path may vary):

    sudo chmod g+rx /var/log/postgresql/
    sudo chmod g+r /var/log/postgresql/*
    
  2. Add the user otelcol to the group postgres:

    sudo usermod --groups=postgres otelcol
    

    Now the collector should be able to read the existing log files.

Additionally, it is necessary to adjust the DBMS instance configuration so that new log files are created with the required access permissions. This is achieved by modifying the log_file_mode parameter and reloading the configuration. The parameter can be updated either directly in the configuration file, via ALTER SYSTEM, or through automation tools and IaC (Infrastructure as Code) solutions.

In the example below, the change is made by connecting to the DBMS instance and using ALTER SYSTEM:

psql -U postgres -c 'ALTER SYSTEM SET log_file_mode TO "0640"'
psql -U postgres -c 'SELECT pg_reload_conf()'

3.6.2. Setting up a DBMS Instance User #

The DBMS user setup consists of the following steps:

  • Creating and configuring the privileges of the DBMS user under which the collector connects to the DBMS instance.

  • Setting up HBA authorization rules that will allow the collector to connect to the DBMS instance.

  • Configuring additional privileges for function execution; this step is optional and is only required if you actually want to enable the collection of the corresponding data.

3.6.2.1. Creating and Setting up a User #

Set a password when creating a user:

sudo -u postgres createuser --pwprompt otelcol

To set up permissions, connect to the DBMS instance and run the following commands:

GRANT pg_monitor TO otelcol;

3.6.2.2. Setting up the HBA Rules #

When using plugins that require connections to other databases (such as collecting tables, indexes, or bloat), the HBA (Host-Based Authentication) rules must be aligned with the collector rules:

  • The databases listed in the plugin configuration must be allowed in the HBA configuration.

  • If the collector is configured to collect data from all databases, then HBA rules should allow connection to all of them.

PostgreSQL DBMS supports a wide variety of authentication methods. When setting up HBA rules, focus on the method that is used in your case.

The example below shows how to set up access to the database postgres using the scram-sha-256 method.

vi pg_hba.conf

local  postgres  otelcol                 scram-sha-256
host   postgres  otelcol  127.0.0.1/32   scram-sha-256

In this example, the connection capability is limited to only the postgres database; if the collector is configured to collect data from other databases, the corresponding allowing rules must be added to the HBA configuration.

Reload the DBMS instance configuration for the changes to take effect:

sudo -u postgres psql -c 'SELECT pg_reload_conf()'

3.6.2.3. Setting up Additional Privileges #

Different types of collected data require access to various internal functions. Access to these functions is restricted for general users, as they can reveal confidential information. Therefore, granting access should be coordinated with the company's security policies.

See Section 1.3.1 for information about the access privileges required for seamless operation.

3.6.3. Setting up the Collector #

3.6.3.1. Connecting to a DBMS Instance #

The connection parameters for the DBMS instance are managed in the postgrespro receiver configuration of the collector configuration file. The user credentials should be specified in the endpoint, database, username, and password parameters (it is possible to pass the password through an environment variable):

receivers:
postgrespro:
  transport: tcp
  endpoint: localhost:5432
  database: postgres
  username: otelcol
  password: ${env:POSTGRESQL_PASSWORD}

3.6.4. Configuring TLS #

TLS (Transport Layer Security) is a protocol that encrypts data transmitted between systems, ensuring confidentiality and integrity. By default, TLS is enabled with server certificate verification using the system root CAs. No additional configuration is needed for standard TLS. This section describes mutual TLS (mTLS), where both client and server present certificates — it is optional and requires additional configuration.

An example of TLS configuration for the otlp_http exporter:

exporters:
  otlp_http:
    endpoint: "https://ppem.example.org"
    tls:
      insecure: false
      insecure_skip_verify: false
      ca_file: server.crt
      cert_file: client.crt
      key_file: client.key
      min_version: "1.3"
      max_version: "1.3"

Warning

  • insecure disables transport security entirely. It is disabled by default (false), and it is strongly recommended to keep it disabled and use mTLS instead; otherwise, metrics will be sent over plain TCP.

  • insecure_skip_verify disables certificate verification and should only be used in testing and development environments. Do not use it in production.

  • insecure and insecure_skip_verify are mutually exclusive.

  • ca_file specifies the path to the TLS certificate to use by the client to verify the server certificate. If omitted, the system root CAs are used. This parameter is required for self-signed certificates.

    Note

    For receivers and the prometheus exporter, use the client_ca_file parameter instead to specify the path to the TLS certificate used by the server to verify the client certificate.

  • cert_file specifies the path to the TLS certificate. For a server, this is required to serve TLS. For a client, this is only needed for mTLS. Default: $HOME/.postgresql/postgresql.crt.

  • key_file specifies the path to the TLS private key. Must be provided alongside cert_file. Default: $HOME/.postgresql/postgresql.key.

  • min_version specifies the minimum acceptable TLS version. Default: "1.2".

  • max_version specifies the maximum acceptable TLS version. Default: "" — the latest supported version is used, which is currently 1.3.

For the full list of TLS configuration parameters, refer to the OpenTelemetry documentation.

3.6.5. Setting up Allowlists and Denylists #

Allowlists and denylists provide granular control over metrics collection from specific databases and objects. This is particularly useful when security policies mandate restricting access to certain databases while allowing collection from others.

Global allowlists and denylists can be configured for plugins at the receiver level. Here is a general example of such configuration:

receivers:
  postgrespro:
    acl:
      databases:
        allow:
          - name: postgres
            schemas:
              - name: public
                tables:
                  - name: table
                  - name: table_index
                    indexes:
                    - name: index1
                    - name: index2
                functions:
                  - name: function1
        deny:
          - name: db
            schemas:
              - name: schema
                tables:
                  - name: table

Where:

  • The acl.allow section defines which databases (and their nested objects) are collected by plugins by default.

  • The acl.deny section specifies databases and objects from which pgpro-otel-collector is prohibited from collecting metrics.

Let's consider a specific example of excluding the zabbix database from data collection:

receivers:
  postgrespro:
    max_threads: 3
    collection_interval: 60s
    initial_delay: 1s
    transport: tcp
    endpoint: localhost:5432
    database: postgres
    username: postgres
    password: ${env:POSTGRESQL_PASSWORD}
    metrics: null
    acl:
      databases:
        allow:
          - name: postgres
        deny:
          - name: zabbix
    plugins:
      activity:
        enabled: true
      bgwriter:
        enabled: true
      locks:
        enabled: true
      version:
        enabled: true
      wal:
        enabled: true
      cache:
        enabled: true

In this example, metrics are collected from the postgres database by default, while collection from the zabbix database is prohibited regardless of other settings.

Individual plugins can have their own databases configuration section:

      tables:
        enabled: true
        databases:
          - name: demo

In this case, plugins override acl.allow but still adhere to the acl.deny restrictions.

3.6.5.1. Using Regular Expressions with ACL #

pgpro-otel-collector supports regular expressions in ACL (Access Control List) configuration for both allowlists and denylists. Regular expressions eliminate the need to manually update ACL configurations when new database objects are created. Instead of listing individual objects, you can define patterns that automatically include or exclude objects based on their names. An example of such a regular expression is shown below.

receivers:
  postgrespro:
    transport: tcp
    endpoint: &endpoint localhost:5432
    database: postgres
    username: postgres
    password: ${env:POSTGRESQL_PASSWORD}
    collection_interval: 60s
    initial_delay: 1s
    max_threads: 3
    plugins:
      databases:
        allow:
          - name: db1.*
            schemas:
              - name: sch1.*
                tables:
                  - name: tb1.*
                  - name: tb2.*
                    indexes:
                    - name: idx2.*
      activity:
        enabled: true
      tables:
        enabled: true
      indexes:
        enabled: true
        # Allowlists can be set up for a specific plugin
        # databases:
        #   - name: db1.*
        #     schemas:
        #       - name: sch1.*
        #         tables:
        #           - name: tb1.*
        #           - name: tb2.*
        #             indexes:
        #             - name: idx2.*
      functions:
        enabled: true
      bloat_tables:
        enabled: true
      bloat_indexes:
        enabled: true

3.6.6. Basic Authenticator #

The basicauth extension is an open-source component of the OpenTelemetry Collector that implements basic HTTP authentication.

Below is the example procedure of enabling basic authentication for the prometheus exporter.

  1. Create a configuration file (for example, auth_basic.yml) with the following content:

    extensions:
      basicauth/prometheus:
        htpasswd:
          # The path to the htpasswd file
          # file: .htpasswd
          #
          # The htpasswd file inline content
          inline: |
           ${env:BASIC_AUTH_USERNAME}:${env:BASIC_AUTH_PASSWORD}
    exporters:
      prometheus:
        endpoint: :8889
        send_timestamps: true
        # TLS configuration for the Prometheus HTTP endpoint.
        # When configured, the exporter will serve HTTPS instead of HTTP.
        # tls:
        #   cert_file: /etc/pgpro-otel-collector/cert.d/server.crt
        #   key_file: /etc/pgpro-otel-collector/cert.d/server.key
        #   client_ca_file: /etc/pgpro-otel-collector/cert.d/ca.crt # mTLS
        #   min_version: "1.3"
        auth:
          authenticator: basicauth/prometheus
    service:
      extensions: [ basicauth/prometheus ]
    

    You must either set htpasswd.file or htpasswd.inline. If both are configured, the htpasswd.inline credentials take precedence.

    For more details on TLS configuration parameters, refer to Section 3.6.4.

  2. Start the collector, providing both the main configuration file and the authentication file:

    BASIC_AUTH_USERNAME=username BASIC_AUTH_PASSWORD=password build/pgpro-otel-collector/pgpro-otel-collector --config configs/basic.yml --config configs/auth_basic.yml
    
  3. Check whether a request without authentication is rejected:

    $ curl 127.0.0.1:8889/metrics
    # Should return an error "no basic auth provided"
    
  4. Check whether a request with valid credentials returns metrics:

    $ curl -u username:password 127.0.0.1:8889/metrics
    # Should return Prometheus metrics