Skip to content

Audit Service Integration

Use this guide to integrate your application with the Industrial Edge Audit Trail service and send security-relevant audit events.

Prerequisites

  • The Audit Event feature is enabled on the Industrial Edge Device. This feature is enabled by default.
  • Your application has access to the audit socket through a volume mount.
  • You know whether you want to use audit-client or the gRPC interface directly.

Socket path summary

The audit service exposes its gRPC interface through a Unix domain socket. The socket path depends on the IEDK version.

IEDK version Socket path
≥ 1.22 and < 1.28 /var/run/devicemodel/audit.sock
≥ 1.28 /var/run/devicemodel/events/audit.sock

If you run your application in a container, mount the host socket path into the container. For detailed interface information, see Audit Service Reference.

Configuring the Docker Compose volume

To communicate with the audit service, mount the host socket path into the container. Because your application cannot detect the IEDK version at runtime, mount the parent directory to support both socket paths.

Proceed as follows:

  1. Open your application's docker-compose.yml file.
  2. Add the following volume configuration:

    services:
      myapp:
        # ... your service configuration ...
        volumes:
          - devicemodel:/var/run/devicemodel
    
    volumes:
      devicemodel:
        driver: local
        driver_opts:
          type: none
          device: /var/run/devicemodel
          o: bind
    

NOTICE

Mount the parent directory
Do not mount only /var/run/devicemodel/events/. This breaks compatibility with IEDK versions earlier than 1.28, where the socket is located at /var/run/devicemodel/audit.sock. If you mount the parent path /var/run/devicemodel, both socket paths are available inside the container.

Sending audit events

Choose one of the following methods.

The audit-client is an internal Go package that simplifies sending audit events.

NOTICE

Using the required audit-client version
Use audit-client version 1.4.1-1 or later. This version includes automatic socket path discovery that is required for compatibility across IEDK versions.

Proceed as follows:

  1. Configure Go to use the private Siemens module registry.
  2. Install or update audit-client.
  3. Send audit events from your application.
go env -w GOPRIVATE=code.siemens.com
go get -u code.siemens.com/industrial-edge/product/industrial-edge-platform/audit-trail/audit-client
Usage example
package main

import (
    "log"

    "code.siemens.com/industrial-edge/product/industrial-edge-platform/audit-trail/audit-client/v1/enums"
    "code.siemens.com/industrial-edge/product/industrial-edge-platform/audit-trail/audit-client/v1/grpcclient"
    "code.siemens.com/industrial-edge/product/industrial-edge-platform/audit-trail/audit-client/v1/proto"
)

func main() {
    grpcclient.SetAppName("my-edge-app")

    if err := grpcclient.NewAuditEvent(enums.SE_CFG_DATA_CHANGED).
        UserID("user@example.com").
        Fct(enums.FCT_IE_DEVICE_SOFTWARE_APP_CONFIGURATION_UPDATE).
        Resource("/config-file-path").
        Result(proto.Result_SUCCESS).
        ClientIP("192.168.1.100").
        Msg("configuration changed"); err != nil {

        log.Printf("Failed to send audit event: %v", err)
    }
}

Starting with version 1.4.1-1, audit-client discovers the correct socket path automatically. You do not need to configure the socket path in your application.

If you use the gRPC interface directly, use the protocol buffer definition and field descriptions from Audit Service Reference.

NOTICE

Checking compiler and reply code requirements
Compile the proto3 file with protoc version 3.15 or later. The list of gRPC reply codes may be extended in the future. For the full list, see gRPC status codes.

Proceed as follows:

  1. Get the latest protobuf definition from Audit-service Interface Spec.
  2. Generate the client code for your programming language.
  3. Connect to the socket path that matches your IEDK version.
  4. Build and send the audit record.
Python example
import grpc

import record_pb2
import record_pb2_grpc

channel = grpc.insecure_channel('unix:///var/run/devicemodel/events/audit.sock')
stub = record_pb2_grpc.AuditTrailStub(channel)

record = record_pb2.AuditRecord(
    apiVersion=1,
    eventID=58,
    appName="my-python-app",
    functionData=record_pb2.FunctionData(
        fct="ie.device.software.app.configuration.update",
        resource="config.json",
        result=record_pb2.Result.SUCCESS,
    ),
    SessionData=record_pb2.SessionData(
        userID="user@example.com",
        src="192.168.1.100",
    ),
    message="User updated app configuration",
)

reply = stub.SendAuditRecord(record)
print(f"Reply: code={reply.code}, status={reply.status}")

Best practices

  1. Check the reply code. If the audit service is disabled (UNAVAILABLE), let your application continue to operate and log that the audit event could not be sent.
  2. Use meaningful fct values. Follow the existing naming convention: ie.device.software.app.<your-domain>.<action>.
  3. Include the client IP address. If your application provides a web UI or API, set SessionData.src for traceability.
  4. Keep messages concise. Use the message field for a short, human-readable summary.
  5. Handle connection failures gracefully. The audit socket can be unavailable for a short time during firmware updates or audit service restarts. Use retry logic with exponential backoff.
  6. Do not modify the socket. Your application must only write to the socket. Do not delete or recreate the socket file.
Complete Docker Compose example
version: '2.4'
services:
  my-app:
    image: my-app:1.0.0
    restart: unless-stopped
    mem_limit: 256m
    volumes:
      - devicemodel:/var/run/devicemodel
      - './app-data/:/app/data/'
    networks:
      - app-network

volumes:
  devicemodel:
    driver: local
    driver_opts:
      type: none
      device: /var/run/devicemodel
      o: bind

networks:
  app-network:
    driver: bridge