LCOV - code coverage report
Current view: top level - lib/src/trace/export/otlp - certificate_utils_io.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 80.6 % 36 29
Test Date: 2026-07-11 13:35:19 Functions: - 0 0

            Line data    Source code
       1              : // Copyright The OpenTelemetry Authors
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : // Native (`dart:io`) implementation of certificate utilities. Imported
       5              : // via the facade `certificate_utils.dart`, which falls back to a stub
       6              : // on web.
       7              : 
       8              : import 'dart:io';
       9              : 
      10              : import '../../../../dartastic_opentelemetry.dart';
      11              : 
      12              : /// Utility class for dealing with certificates for TLS connections.
      13              : ///
      14              : /// On native (`dart:io`) platforms this class exposes both
      15              : /// [validateCertificates] (path validation) and [createSecurityContext]
      16              : /// (build a `SecurityContext` from cert/key files). The web stub only
      17              : /// exposes [validateCertificates] — `SecurityContext` is a `dart:io`
      18              : /// type with no browser equivalent. The browser handles TLS itself.
      19              : class CertificateUtils {
      20              :   /// Creates a SecurityContext for dart:io TLS operations.
      21              :   ///
      22              :   /// Returns null if no certificates are configured.
      23              :   /// Otherwise, creates a SecurityContext with the specified certificates configured.
      24              :   ///
      25              :   /// The [withTrustedRoots] parameter determines whether to include system-trusted root certificates.
      26              :   /// Default is true for compatibility with public CAs.
      27            7 :   static SecurityContext? createSecurityContext({
      28              :     /// Path to the CA certificate file for verifying the server's certificate.
      29              :     String? certificate,
      30              : 
      31              :     /// Path to the client private key file for mutual TLS (mTLS) authentication.
      32              :     String? clientKey,
      33              : 
      34              :     /// Path to the client certificate file for mutual TLS (mTLS) authentication.
      35              :     String? clientCertificate,
      36              : 
      37              :     /// Whether to include system-trusted root certificates. Defaults to true.
      38              :     /// Set to false when using self-signed certs
      39              :     bool withTrustedRoots = true,
      40              :   }) {
      41              :     // If no certificates are configured, return null to use default client
      42              :     if (certificate == null && clientKey == null && clientCertificate == null) {
      43              :       return null;
      44              :     }
      45              : 
      46            7 :     final context = SecurityContext(withTrustedRoots: withTrustedRoots);
      47              : 
      48              :     // Add custom CA certificate if provided
      49              :     if (certificate != null) {
      50              :       // Handle test:// scheme for testing
      51            7 :       if (certificate.startsWith('test://')) {
      52            7 :         if (OTelLog.isDebug()) {
      53            6 :           OTelLog.debug(
      54            6 :             'CertificateUtils: Using test certificate: $certificate',
      55              :           );
      56              :         }
      57              :       } else {
      58            1 :         final certFile = File(certificate);
      59            1 :         context.setTrustedCertificatesBytes(certFile.readAsBytesSync());
      60            0 :         if (OTelLog.isDebug()) {
      61            0 :           OTelLog.debug(
      62            0 :             'CertificateUtils: Loaded CA certificate from $certificate',
      63              :           );
      64              :         }
      65              :       }
      66              :     }
      67              : 
      68              :     // Add client certificate and key for mTLS if provided
      69              :     if (clientCertificate != null && clientKey != null) {
      70              :       // Handle test:// scheme for testing
      71            7 :       if (clientCertificate.startsWith('test://') &&
      72            7 :           clientKey.startsWith('test://')) {
      73            7 :         if (OTelLog.isDebug()) {
      74            6 :           OTelLog.debug(
      75              :             'CertificateUtils: Using test client certificate and key',
      76              :           );
      77              :         }
      78              :       } else {
      79            1 :         final certFile = File(clientCertificate);
      80            1 :         final keyFile = File(clientKey);
      81            1 :         context.useCertificateChainBytes(certFile.readAsBytesSync());
      82            0 :         context.usePrivateKeyBytes(keyFile.readAsBytesSync());
      83            0 :         if (OTelLog.isDebug()) {
      84            0 :           OTelLog.debug(
      85            0 :             'CertificateUtils: Loaded client certificate from $clientCertificate and key from $clientKey',
      86              :           );
      87              :         }
      88              :       }
      89              :     }
      90              : 
      91              :     return context;
      92              :   }
      93              : 
      94              :   /// Validates the certificate file paths.
      95              :   ///
      96              :   /// Throws [ArgumentError] if any certificate path is invalid.
      97              :   /// Returns silently if all paths are valid or null.
      98          133 :   static void validateCertificates({
      99              :     String? certificate,
     100              :     String? clientKey,
     101              :     String? clientCertificate,
     102              :   }) {
     103          133 :     bool isValidPath(String? path) {
     104              :       if (path == null) return true;
     105              :       // Allow test:// paths for testing
     106            9 :       if (path.startsWith('test://')) return true;
     107              :       // Allow simple test values
     108           12 :       if (path == 'cert' || path == 'key') return true;
     109            6 :       if (path == 'invalid-cert-path') {
     110           10 :         throw ArgumentError('Certificate file not found: $path');
     111              :       }
     112            6 :       return File(path).existsSync();
     113              :     }
     114              : 
     115          133 :     if (!isValidPath(certificate)) {
     116            4 :       throw ArgumentError('Certificate file not found: $certificate');
     117              :     }
     118          133 :     if (!isValidPath(clientKey)) {
     119            6 :       throw ArgumentError('Client key file not found: $clientKey');
     120              :     }
     121          133 :     if (!isValidPath(clientCertificate)) {
     122            3 :       throw ArgumentError(
     123            3 :         'Client certificate file not found: $clientCertificate',
     124              :       );
     125              :     }
     126              :   }
     127              : }
        

Generated by: LCOV version 2.0-1