From fcdbc192c761129669c616db75f53d4426bf2cb2 Mon Sep 17 00:00:00 2001 From: Aphral Griffin Date: Mon, 7 Jul 2025 17:15:33 +0100 Subject: [PATCH 01/12] update go verion and golangci-lint --- .golangci.yml | 1371 +++++++---------- Makefile.tools | 2 +- go.mod | 4 +- .../nginxossreceiver/factory_test.go | 2 +- .../operator/input/file/config_test.go | 2 +- internal/collector/otel_collector_plugin.go | 2 +- .../datasource/config/nginx_config_parser.go | 7 +- .../nginx_config_parser_benchmark_test.go | 5 +- .../config/nginx_config_parser_test.go | 2 +- internal/file/file_manager_service.go | 4 +- internal/file/file_service_operator.go | 4 +- internal/logger/logger.go | 3 +- internal/plugin/plugin_manager_test.go | 2 +- internal/resource/nginx_instance_operator.go | 2 +- internal/resource/resource_plugin.go | 5 +- internal/resource/resource_plugin_test.go | 2 +- internal/resource/resource_service.go | 10 +- .../instance/instance_watcher_service.go | 2 +- .../nginx-app-protect-instance-watcher.go | 12 +- .../instance/nginx_process_parser_test.go | 8 +- pkg/id/uuid.go | 8 +- scripts/packages/packager/Dockerfile | 2 +- test/helpers/go_utils_test.go | 2 +- test/helpers/os_utils_test.go | 2 +- .../grpc/mock_management_command_service.go | 8 +- .../mock/grpc/mock_management_file_service.go | 28 +- 26 files changed, 626 insertions(+), 875 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 020a7ff63..5d0832068 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,21 +1,10 @@ -issues: - exclude-files: - - ".*gen.go" - - ".pb.go" - - ".pb.validate.go" - - ".*/generated_[A-Za-z_]*\\.go" - exclude-dirs: - - ".*fakes" # Skip mock directories -run: - timeout: 3m +version: "2" linters: - # By default, the enabled linters are: - # errcheck, gosimple, govet, ineffassign, staticcheck, unused enable: - bodyclose - - cyclop - - copyloopvar - contextcheck + - copyloopvar + - cyclop - dupl - errorlint - exhaustive @@ -26,7 +15,6 @@ linters: - gocritic - gocyclo - godox - - gofumpt - goheader - gomoddirectives - gosec @@ -57,7 +45,7 @@ linters: - rowserrcheck - sloglint - sqlclosecheck - - stylecheck + - staticcheck - tagalign - testableexamples - testifylint @@ -68,803 +56,558 @@ linters: - wastedassign - whitespace - zerologlint + settings: + cyclop: + max-complexity: 10 + package-average: 0 + errorlint: + errorf: true + errorf-multi: false + asserts: false + comparison: false + gocognit: + min-complexity: 20 + goconst: + match-constant: true + min-len: 2 + min-occurrences: 3 + numbers: false + min: 3 + max: 3 + ignore-calls: true + gocritic: + settings: + captLocal: + paramsOnly: false + elseif: + skipBalanced: true + ifElseChain: + minThreshold: 4 + gocyclo: + min-complexity: 20 + godox: + keywords: + - TODO + - BUG + - FIXME + - HACK + goheader: + template: |- + Copyright (c) F5, Inc. -# Allows configuring linters that support configuration. -# Refer to full list of linters here: https://golangci-lint.run/usage/linters/. -linters-settings: - unused: - # Mark all struct fields that have been written to as used. Default: true - field-writes-are-uses: true - # Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just wr◊ite. Default: false - post-statements-are-reads: true - # Mark all exported fields as used. Default: true - exported-fields-are-used: false - # Mark all function parameters as used. Default: true - parameters-are-used: true - # Mark all local variables as used. Default: true - local-variables-are-used: false - # Mark all identifiers inside generated files as used. Default: true - generated-is-used: true - cyclop: - # The maximal code complexity to report. Default: 10 - max-complexity: 10 - # The maximal average package complexity. If it's higher than 0.0 (float) the check is enabled. Default: 0.0 - package-average: 0.0 - skip-tests: true - govet: - settings: - shadow: - # Report about shadowed variables. Default: false - strict: true - # Each analyzer can be configured separately in the 'settings:' section. - # settings: - # Run `go tool vet help` to see all analyzers. Default: false - enable-all: true - errorlint: - # Check whether fmt.Errorf uses the %w verb for formatting errors. - # See the https://github.com/polyfloyd/go-errorlint for caveats. Default: true - errorf: true - # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true) Default: true - errorf-multi: false - # Check for plain type assertions and type switches. Default: true - asserts: false - # Check for plain error comparisons. Default: true - comparison: false - gci: - # Enable custom order of sections. If `true`, make the section order the same as the order of `sections`. - # Default: false - custom-order: true - # Section configuration to compare against. - # Section names are case-insensitive and may contain parameters in (). - # The default order of sections is `standard > default > custom > blank > dot`, - # If `custom-order` is `true`, it follows the order of `sections` option. - # Default: ["standard", "default"] - sections: - - standard # Standard section: captures all standard packages. - - default # Default section: contains all imports that could not be matched to another section type. - - prefix(github.com/nginx/agent) # Custom section: groups all imports with the specified Prefix. - - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. - - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. - # Skip generated files. - # Default: true - skip-generated: true - gocognit: - # Minimal code complexity to report. Default: 30 (but we recommend 10-20) - min-complexity: 20 - goconst: - # Minimal length of string constant. Default: 3 - min-len: 2 - # Minimum occurrences of constant string count to trigger issue. Default: 3 - min-occurrences: 3 - # Ignore test files. Default: false - ignore-tests: true - # Look for existing constants matching the values. Default: true - match-constant: true - # Search also for duplicated numbers. Default: false - numbers: false - # Minimum value, only works with goconst.numbers. Default: 3 - min: 3 - # Maximum value, only works with goconst.numbers. Default: 3 - max: 3 - # Ignore when constant is not used as function argument. Default: true - ignore-calls: true - gocritic: - # Which checks should be enabled; can't be combined with 'disabled-checks'. - # See https://go-critic.github.io/overview#checks-overview. - # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`. - # By default, list of stable checks is used. - # enabled-checks: - # - nestingReduce - # - unnamedResult - # - ruleguard - # - truncateCmp - # Which checks should be disabled; can't be combined with 'enabled-checks'. - # Default: [] - disabled-checks: [] - # Settings passed to gocritic. - # The settings key is the name of a supported gocritic checker. - # The list of supported checkers can be find in https://go-critic.github.io/overview. - settings: - # Must be valid enabled check name. - captLocal: - # Whether to restrict checker to params only. Default: true - paramsOnly: false - elseif: - # Whether to skip balanced if-else pairs. Default: true - skipBalanced: true - ifElseChain: - # Min number of if-else blocks that makes the warning trigger. Default: 2 - minThreshold: 4 - gocyclo: - # Minimal code complexity to report. Default: 30 (but we recommend 10-20) - min-complexity: 20 - godox: - # Report any comments starting with keywords, this is useful for TODO or FIXME comments that - # might be left in the code accidentally and should be resolved before merging. Default: ["TODO", "BUG", "FIXME"] - keywords: - - TODO - - BUG - - FIXME - - HACK - gofumpt: - # Module path which contains the source code being formatted. Default: "" - module-path: github.com/nginx/agent - # Choose whether to use the extra rules. Default: false - extra-rules: true - goheader: - # The template use for checking. - # Default: "" - template: |- - Copyright (c) F5, Inc. - - This source code is licensed under the Apache License, Version 2.0 license found in the - LICENSE file in the root directory of this source tree. - gomoddirectives: - # Allow local `replace` directives. Default: false - replace-local: false - # List of allowed `replace` directives. Default: [] - replace-allow-list: [] - # Allow to not explain why the version has been retracted in the `retract` directives. Default: false - retract-allow-no-explanation: false - # Forbid the use of the `exclude` directives. Default: false - exclude-forbidden: false - gosec: - # To select a subset of rules to run. - # Available rules: https://github.com/securego/gosec#available-rules. Default: [] - means include all rules - includes: - - G101 # Look for hard coded credentials - - G102 # Bind to all interfaces - - G103 # Audit the use of unsafe block - - G104 # Audit errors not checked - - G106 # Audit the use of ssh.InsecureIgnoreHostKey - - G107 # Url provided to HTTP request as taint input - - G108 # Profiling endpoint automatically exposed on /debug/pprof - - G109 # Potential Integer overflow made by strconv.Atoi result conversion to int16/32 - - G110 # Potential DoS vulnerability via decompression bomb - - G111 # Potential directory traversal - - G112 # Potential slowloris attack - - G113 # Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772) - - G114 # Use of net/http serve function that has no support for setting timeouts - - G201 # SQL query construction using format string - - G202 # SQL query construction using string concatenation - - G203 # Use of unescaped data in HTML templates - - G204 # Audit use of command execution - - G301 # Poor file permissions used when creating a directory - - G302 # Poor file permissions used with chmod - - G303 # Creating tempfile using a predictable path - - G304 # File path provided as taint input - - G305 # File traversal when extracting zip/tar archive - - G306 # Poor file permissions used when writing to a new file - - G307 # Poor file permissions used when creating a file with host.Create - - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - - G402 # Look for bad TLS connection settings - - G403 # Ensure minimum RSA key length of 2048 bits - - G404 # Insecure random number source (rand) - - G501 # Import blocklist: crypto/md5 - - G502 # Import blocklist: crypto/des - - G503 # Import blocklist: crypto/rc4 - - G504 # Import blocklist: net/http/cgi - - G505 # Import blocklist: crypto/sha1 - - G602 # Slice access out of bounds - # Exclude generated files - # Default: false - exclude-generated: true - # Filter out the issues with a lower severity than the given value. - # Valid options are: low, medium, high. - # Default: low - severity: low - # Filter out the issues with a lower confidence than the given value. - # Valid options are: low, medium, high. Default: low - confidence: medium - # To specify the configuration of rules. - config: - # Globals are applicable to all rules. - global: - # If true, ignore #nosec in comments (and an alternative as well). - # Default: false - nosec: false - # Add an alternative comment prefix to #nosec (both will work at the same time). Default: "" - "#nosec": "" - # Define whether nosec issues are counted as finding or not. Default: false - show-ignored: false - # Audit mode enables addition checks that for normal code analysis might be too nosy. Default: false - audit: false - G101: - # Regexp pattern for variables and constants to find. - # Default: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" - pattern: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" - # If true, complain about all cases (even with low entropy). Default: false - ignore_entropy: false - # Maximum allowed entropy of the string. Default: "80.0" - entropy_threshold: "80.0" - # Maximum allowed value of entropy/string length. - # Is taken into account if entropy >= entropy_threshold/2. Default: "3.0" - per_char_threshold: "3.0" - # Calculate entropy for first N chars of the string. Default: "16" - truncate: "16" - G111: - # Regexp pattern to find potential directory traversal. Default: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" - pattern: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" - # Maximum allowed permissions mode for host.Mkdir and host.MkdirAll. Default: "0750" - G301: "0750" - # Maximum allowed permissions mode for host.OpenFile and host.Chmod. Default: "0600" - G302: "0600" - # Maximum allowed permissions mode for host.WriteFile and ioutil.WriteFile. Default: "0600" - G306: "0600" - grouper: - # Require the use of a single global 'const' declaration only. Default: false - const-require-single-const: false - # Require the use of grouped global 'const' declarations. Default: false - const-require-grouping: false - # Require the use of a single 'import' declaration only. Default: false - import-require-single-import: false - # Require the use of grouped 'import' declarations. Default: false - import-require-grouping: false - # Require the use of a single global 'type' declaration only. Default: false - type-require-single-type: false - # Require the use of grouped global 'type' declarations. Default: false - type-require-grouping: false - # Require the use of a single global 'var' declaration only. Default: false - var-require-single-var: false - # Require the use of grouped global 'var' declarations. - # Default: false - var-require-grouping: false - importas: - # Do not allow unaliased imports of aliased packages. Default: false - no-unaliased: true - # Do not allow non-required aliases. Default: false - no-extra-aliases: false - # List of aliases. Default: [] - alias: - - pkg: "go.opentelemetry.io/otel/sdk/metric" - alias: "metricSdk" - interfacebloat: - # The maximum number of methods allowed for an interface. Default: 10 - max: 10 - ireturn: - # ireturn does not allow using `allow` and `reject` settings at the same time. - # Both settings are lists of the keywords and regular expressions matched to interface or package names. - # keywords: - # - `empty` for `interface{}` - # - `error` for errors - # - `stdlib` for standard library - # - `anon` for anonymous interfaces - # - `generic` for generic interfaces added in go 1.18 - # By default, it allows using errors, empty interfaces, anonymous interfaces, - # and interfaces provided by the standard library. - allow: - - anon - - error - - empty - - stdlib - - google.golang.org/grpc/credentials - - github.com/testcontainers/testcontainers-go - - google.golang.org/grpc - lll: - # Max line length, lines longer will be reported. - # '\t' is counted as 1 character by default, and can be changed with the tab-width option. - # Default: 120. - line-length: 120 - # Tab width in spaces. - # Default: 1 - tab-width: 4 - maintidx: - # Show functions with maintainability index lower than N. - # A high index indicates better maintainability (it's kind of the opposite of complexity). Default: 20 - under: 20 - makezero: - # Allow only slices initialized with a length of zero. Default: false - always: false - misspell: - # Correct spellings using locale preferences for US or UK. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - # Default is to use a neutral variety of English. - locale: "US" - # Default: [] - ignore-words: [] - nakedret: - # Make an issue if func has more lines of code than this setting, and it has naked returns. Default: 30 - max-func-lines: 31 - nestif: - # Minimal complexity of if statements to report. Default: 5 - min-complexity: 5 - nilnil: - # Checks that there is no simultaneous return of `nil` error and an invalid value. - # Default: ["ptr", "func", "iface", "map", "chan"] - checked-types: - - ptr - - func - - iface - - map - - chan - nlreturn: - # Size of the block (including return statement that is still "OK") so no return split required. Default: 1 - block-size: 2 - prealloc: - # IMPORTANT: we don't recommend using this linter before doing performance profiling. - # For most programs usage of prealloc will be a premature optimization. - # Report pre-allocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. - # Default: true - simple: true - # Report pre-allocation suggestions on range loops. - # Default: true - range-loops: true - # Report pre-allocation suggestions on for loops. - # Default: false - for-loops: false - predeclared: - # Comma-separated list of predeclared identifiers to not report on. Default: "" - ignore: "" - # Include method names and field names (i.e., qualified names) in checks. Default: false - q: false - promlinter: - # Promlinter cannot infer all metrics name in static analysis. - # Enable strict mode will also include the errors caused by failing to parse the args. - # Default: false - strict: false - # Please refer to https://github.com/yeya24/promlinter#usage for detailed usage. - # Default: [] - disabled-linters: [] - reassign: - # Patterns for global variable names that are checked for reassignment. - # See https://github.com/curioswitch/go-reassign#usage - # Default: ["EOF", "Err.*"] - patterns: - - "Err.*" - - "EOF" - revive: - # Maximum number of open files at the same time. Defaults to unlimited. - max-open-files: 2048 - # When set to false, ignores files with "GENERATED" header, similar to golint. Default: false - ignore-generated-header: false - # Sets the default severity. Default: warning - severity: warning - # Enable all available rules. Default: false - enable-all-rules: false - # Sets the default failure confidence. This means that linting errors with less than 0.8 confidence will be ignored. - # Default: 0.8 - confidence: 0.8 + This source code is licensed under the Apache License, Version 2.0 license found in the + LICENSE file in the root directory of this source tree. + gomoddirectives: + replace-local: false + exclude-forbidden: false + retract-allow-no-explanation: false + gosec: + includes: + - G101 + - G102 + - G103 + - G104 + - G106 + - G107 + - G108 + - G109 + - G110 + - G111 + - G112 + - G113 + - G114 + - G201 + - G202 + - G203 + - G204 + - G301 + - G302 + - G303 + - G304 + - G305 + - G306 + - G307 + - G401 + - G402 + - G403 + - G404 + - G501 + - G502 + - G503 + - G504 + - G505 + - G602 + severity: low + confidence: medium + config: + G101: + entropy_threshold: "80.0" + ignore_entropy: false + pattern: (?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred + per_char_threshold: "3.0" + truncate: "16" + G111: + pattern: http\.Dir\("\/"\)|http\.Dir\('\/'\) + G301: "0750" + G302: "0600" + G306: "0600" + global: + '#nosec': "" + audit: false + nosec: false + show-ignored: false + govet: + enable-all: true + settings: + shadow: + strict: true + grouper: + const-require-single-const: false + const-require-grouping: false + import-require-single-import: false + import-require-grouping: false + type-require-single-type: false + type-require-grouping: false + var-require-single-var: false + var-require-grouping: false + importas: + alias: + - pkg: go.opentelemetry.io/otel/sdk/metric + alias: metricSdk + no-unaliased: true + no-extra-aliases: false + interfacebloat: + max: 10 + ireturn: + allow: + - anon + - error + - empty + - stdlib + - google.golang.org/grpc/credentials + - github.com/testcontainers/testcontainers-go + - google.golang.org/grpc + lll: + line-length: 120 + tab-width: 4 + maintidx: + under: 20 + makezero: + always: false + misspell: + locale: US + nakedret: + max-func-lines: 31 + nestif: + min-complexity: 5 + nilnil: + checked-types: + - ptr + - func + - iface + - map + - chan + nlreturn: + block-size: 2 + prealloc: + simple: true + range-loops: true + for-loops: false + predeclared: + qualified-name: false + promlinter: + strict: false + reassign: + patterns: + - Err.* + - EOF + revive: + max-open-files: 2048 + confidence: 0.8 + severity: warning + enable-all-rules: false + rules: + - name: add-constant + arguments: + - allowFloats: 0.0,0.,1.0,1.,2.0,2. + allowInts: 0,1,2 + allowStrs: '""' + ignoreFuncs: host\.* + maxLitCount: "3" + severity: warning + disabled: true + - name: argument-limit + arguments: + - 5 + severity: warning + disabled: false + - name: atomic + severity: warning + disabled: false + - name: banned-characters + arguments: + - Ω + - Σ + - σ + severity: warning + disabled: false + - name: bare-return + severity: warning + disabled: false + - name: blank-imports + severity: warning + disabled: false + - name: bool-literal-in-expr + severity: warning + disabled: false + - name: call-to-gc + severity: warning + disabled: false + - name: cognitive-complexity + arguments: + - 10 + severity: warning + disabled: false + - name: comment-spacings + severity: warning + disabled: true + - name: confusing-naming + severity: warning + disabled: false + - name: confusing-results + severity: warning + disabled: false + - name: constant-logical-expr + severity: warning + disabled: false + - name: context-as-argument + arguments: + - allowTypesBefore: '*testing.T' + severity: warning + disabled: false + - name: context-keys-type + severity: warning + disabled: false + - name: cyclomatic + arguments: + - 10 + severity: warning + disabled: false + - name: datarace + severity: warning + disabled: false + - name: deep-exit + severity: warning + disabled: false + - name: defer + arguments: + - - call-chain + - loop + severity: warning + disabled: false + - name: dot-imports + severity: warning + disabled: false + - name: duplicated-imports + severity: warning + disabled: false + - name: early-return + arguments: + - preserveScope + severity: warning + disabled: false + - name: empty-block + severity: warning + disabled: false + - name: empty-lines + severity: warning + disabled: false + - name: enforce-map-style + arguments: + - make + severity: warning + disabled: false + - name: error-naming + severity: warning + disabled: false + - name: error-return + severity: warning + disabled: false + - name: error-strings + severity: warning + disabled: false + - name: errorf + severity: warning + disabled: false + - name: flag-parameter + severity: warning + disabled: false + - name: function-result-limit + arguments: + - 3 + severity: warning + disabled: false + - name: get-return + severity: warning + disabled: false + - name: identical-branches + severity: warning + disabled: false + - name: if-return + severity: warning + disabled: false + - name: increment-decrement + severity: warning + disabled: false + - name: indent-error-flow + arguments: + - preserveScope + severity: warning + disabled: false + - name: import-alias-naming + arguments: + - ^[a-z][a-zA-Z0-9]{0,}$ + severity: warning + disabled: false + - name: imports-blocklist + arguments: + - crypto/md5 + - crypto/sha1 + severity: warning + disabled: false + - name: import-shadowing + severity: warning + disabled: false + - name: max-public-structs + arguments: + - 3 + severity: warning + disabled: true + - name: modifies-parameter + severity: warning + disabled: false + - name: modifies-value-receiver + severity: warning + disabled: false + - name: nested-structs + severity: warning + disabled: false + - name: optimize-operands-order + severity: warning + disabled: false + - name: package-comments + severity: warning + disabled: false + - name: range + severity: warning + disabled: false + - name: range-val-in-closure + severity: warning + disabled: false + - name: range-val-address + severity: warning + disabled: false + - name: receiver-naming + severity: warning + disabled: false + - name: redundant-import-alias + severity: warning + disabled: false + - name: redefines-builtin-id + severity: warning + disabled: false + - name: string-of-int + severity: warning + disabled: false + - name: string-format + arguments: + - - core.WriteError[1].Message + - /^([^A-Z]|$)/ + - must not start with a capital letter + - - fmt.Errorf[0] + - /(^|[^\.!?])$/ + - must not end in punctuation + - - panic + - /^[^\n]*$/ + - must not contain line breaks + severity: warning + disabled: true + - name: struct-tag + arguments: + - json,inline + - bson,outline,gnu + severity: warning + disabled: false + - name: superfluous-else + arguments: + - preserveScope + severity: warning + disabled: false + - name: time-equal + severity: warning + disabled: false + - name: time-naming + severity: warning + disabled: false + - name: var-naming + arguments: + - - ID + - - VM + - - upperCaseConst: true + severity: warning + disabled: true + - name: var-declaration + severity: warning + disabled: false + - name: unconditional-recursion + severity: warning + disabled: false + - name: unexported-naming + severity: warning + disabled: false + - name: unexported-return + severity: warning + disabled: false + - name: unhandled-error + arguments: + - fmt.Printf + - myFunction + severity: warning + disabled: true + - name: unnecessary-stmt + severity: warning + disabled: false + - name: unreachable-code + severity: warning + disabled: false + - name: unused-parameter + arguments: + - allowRegex: ^_ + severity: warning + disabled: true + - name: unused-receiver + arguments: + - allowRegex: ^_ + severity: warning + disabled: true + - name: useless-break + severity: warning + disabled: false + - name: waitgroup-by-value + severity: warning + disabled: false + rowserrcheck: + packages: + - github.com/jmoiron/sqlx + sloglint: + no-mixed-args: true + kv-only: false + attr-only: false + context: "scope" + static-msg: false + no-raw-keys: false + key-naming-case: snake + args-on-sep-lines: false + tagalign: + align: true + sort: true + order: + - json + - yaml + - yml + - toml + - mapstructure + - binding + - validate + strict: false + testifylint: + enable-all: true + suite-extra-assert-call: + mode: remove + thelper: + test: + first: true + name: false + begin: true + fuzz: + first: true + name: false + begin: true + benchmark: + first: true + name: false + begin: true + tb: + first: true + name: false + begin: true + unparam: + check-exported: true + unused: + field-writes-are-uses: true + post-statements-are-reads: true + exported-fields-are-used: false + parameters-are-used: true + local-variables-are-used: false + generated-is-used: true + usestdlibvars: + http-method: true + http-status-code: true + time-weekday: true + time-month: true + time-layout: true + crypto-hash: true + default-rpc-path: true + sql-isolation-level: true + tls-signature-scheme: true + constant-kind: true + whitespace: + multi-if: false + multi-func: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling rules: - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#add-constant: - - name: add-constant - severity: warning - disabled: true - arguments: - - maxLitCount: "3" - allowStrs: '""' - allowInts: "0,1,2" - allowFloats: "0.0,0.,1.0,1.,2.0,2." - ignoreFuncs: "host\\.*" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#argument-limit - - name: argument-limit - severity: warning - disabled: false - arguments: [ 5 ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#atomic - - name: atomic - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#banned-characters - - name: banned-characters - severity: warning - disabled: false - arguments: [ "Ω", "Σ", "σ"] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bare-return - - name: bare-return - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#blank-imports - - name: blank-imports - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr - - name: bool-literal-in-expr - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#call-to-gc - - name: call-to-gc - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cognitive-complexity - - name: cognitive-complexity - severity: warning - disabled: false - arguments: [ 10 ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#comment-spacings - - name: comment-spacings - severity: warning - disabled: true - arguments: [] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-naming - - name: confusing-naming - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-results - - name: confusing-results - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#constant-logical-expr - - name: constant-logical-expr - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-as-argument - - name: context-as-argument - severity: warning - disabled: false - arguments: - - allowTypesBefore: "*testing.T" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-keys-type - - name: context-keys-type - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cyclomatic - - name: cyclomatic - severity: warning - disabled: false - arguments: [ 10 ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#datarace - - name: datarace - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#deep-exit - - name: deep-exit - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#defer - - name: defer - severity: warning - disabled: false - arguments: - - [ "call-chain", "loop" ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#dot-imports - - name: dot-imports - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#duplicated-imports - - name: duplicated-imports - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return - - name: early-return - severity: warning - disabled: false - arguments: - - "preserveScope" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block - - name: empty-block - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines - - name: empty-lines - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-map-style - - name: enforce-map-style - severity: warning - disabled: false - arguments: - - "make" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming - - name: error-naming - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-return - - name: error-return - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-strings - - name: error-strings - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#errorf - - name: errorf - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#flag-parameter - - name: flag-parameter - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-result-limit - - name: function-result-limit - severity: warning - disabled: false - arguments: [ 3 ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#get-return - - name: get-return - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#identical-branches - - name: identical-branches - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#if-return - - name: if-return - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#increment-decrement - - name: increment-decrement - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow - - name: indent-error-flow - severity: warning - disabled: false - arguments: - - "preserveScope" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-alias-naming - - name: import-alias-naming - severity: warning - disabled: false - arguments: - - "^[a-z][a-zA-Z0-9]{0,}$" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blacklist - - name: imports-blacklist - severity: warning - disabled: false - arguments: - - "crypto/md5" - - "crypto/sha1" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing - - name: import-shadowing - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-public-structs - - name: max-public-structs - severity: warning - disabled: true - arguments: [ 3 ] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-parameter - - name: modifies-parameter - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-value-receiver - - name: modifies-value-receiver - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#nested-structs - - name: nested-structs - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#optimize-operands-order - - name: optimize-operands-order - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#package-comments - - name: package-comments - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range - - name: range - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-in-closure - - name: range-val-in-closure - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-address - - name: range-val-address - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#receiver-naming - - name: receiver-naming - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias - - name: redundant-import-alias - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id - - name: redefines-builtin-id - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-of-int - - name: string-of-int - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format - - name: string-format - severity: warning - disabled: true - arguments: - - - 'core.WriteError[1].Message' - - '/^([^A-Z]|$)/' - - must not start with a capital letter - - - 'fmt.Errorf[0]' - - '/(^|[^\.!?])$/' - - must not end in punctuation - - - panic - - '/^[^\n]*$/' - - must not contain line breaks - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag - - name: struct-tag - arguments: - - "json,inline" - - "bson,outline,gnu" - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else - - name: superfluous-else - severity: warning - disabled: false - arguments: - - "preserveScope" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal - - name: time-equal - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-naming - - name: time-naming - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming - - name: var-naming - severity: warning - disabled: true - arguments: - - [ "ID" ] # AllowList - - [ "VM" ] # DenyList - - - upperCaseConst: true - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration - - name: var-declaration - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unconditional-recursion - - name: unconditional-recursion - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-naming - - name: unexported-naming - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return - - name: unexported-return - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unhandled-error - - name: unhandled-error - severity: warning - disabled: true - arguments: - - "fmt.Printf" - - "myFunction" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unnecessary-stmt - - name: unnecessary-stmt - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unreachable-code - - name: unreachable-code - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter - - name: unused-parameter - severity: warning - disabled: true - arguments: - - allowRegex: "^_" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver - - name: unused-receiver - severity: warning - disabled: true - arguments: - - allowRegex: "^_" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break - - name: useless-break - severity: warning - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value - - name: waitgroup-by-value - severity: warning - disabled: false - rowserrcheck: - # database/sql is always checked - # Default: [] - packages: - - github.com/jmoiron/sqlx - sloglint: - # Enforce not mixing key-value pairs and attributes. Default: true - no-mixed-args: true - # Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only). Default: false - kv-only: false - # Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only). Default: false - attr-only: false - # Enforce using methods that accept a context. Default: false - context: "" - # Enforce using static values for log messages. Default: false - static-msg: false - # Enforce using constants instead of raw keys. Default: false - no-raw-keys: false - # Enforce a single key naming convention. Values: snake, kebab, camel, pascal. Default: "" - key-naming-case: snake - # Enforce putting arguments on separate lines. Default: false - args-on-sep-lines: false - tagalign: - # Whether enable align. If true, the struct tags will be aligned. Default: true. - align: true - # If true, the tags will be sorted by name in ascending order. - # eg: `xml:"bar" json:"bar" validate:"required"` -> `json:"bar" validate:"required" xml:"bar"` - # Default: true - sort: true - # Specify the order of tags, the other tags will be sorted by name. - # This option will be ignored if `sort` is false. - # Default: [] - order: - - json - - yaml - - yml - - toml - - mapstructure - - binding - - validate - # Whether enable strict style. - # In this style, the tags will be sorted and aligned in the dictionary order, - # and the tags with the same name will be aligned together. - # Note: This option will be ignored if 'align' or 'sort' is false. - # Default: false - strict: false - testifylint: - # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). - # Default: false - enable-all: true - suite-extra-assert-call: - # To require or remove extra Assert() call? - # Default: remove - mode: remove - thelper: - test: - # Check *testing.T is first param (or after context.Context) of helper function. - # Default: true - first: true - # Check *testing.T param has name t. Default: true - name: false - # Check t.Helper() begins helper function. Default: true - begin: true - benchmark: - # Check *testing.B is first param (or after context.Context) of helper function. Default: true - first: true - # Check *testing.B param has name b. Default: true - name: false - # Check b.Helper() begins helper function. Default: true - begin: true - tb: - # Check *testing.TB is first param (or after context.Context) of helper function. Default: true - first: true - # Check *testing.TB param has name tb. Default: true - name: false - # Check tb.Helper() begins helper function. Default: true - begin: true - fuzz: - # Check *testing.F is first param (or after context.Context) of helper function. Default: true - first: true - # Check *testing.F param has name f. Default: true - name: false - # Check f.Helper() begins helper function. Default: true - begin: true - unparam: - # Inspect exported functions. Default: false - check-exported: true - usestdlibvars: - # Suggest the use of http.MethodXX. Default: true - http-method: true - # Suggest the use of http.StatusXX. Default: true - http-status-code: true - # Suggest the use of time.Weekday.String(). Default: true - time-weekday: true - # Suggest the use of time.Month.String(). Default: false - time-month: true - # Suggest the use of time.Layout. Default: false - time-layout: true - # Suggest the use of crypto.Hash.String(). Default: false - crypto-hash: true - # Suggest the use of rpc.DefaultXXPath. Default: false - default-rpc-path: true - # Suggest the use of sql.LevelXX.String(). Default: false - sql-isolation-level: true - # Suggest the use of tls.SignatureScheme.String(). Default: false - tls-signature-scheme: true - # Suggest the use of constant.Kind.String(). Default: false - constant-kind: true - whitespace: - # Enforces newlines (or comments) after every multi-line if statement. Default: false - multi-if: false - # Enforces newlines (or comments) after every multi-line function signature. Default: false - multi-func: false + - linters: + - cyclop + - goconst + path: (.+)_test\.go + paths: + - .*gen.go + - .pb.go + - .pb.validate.go + - .*/generated_[A-Za-z_]*\.go + - .*fakes + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofumpt + settings: + gci: + sections: + - standard + - default + - prefix(github.com/nginx/agent) + - blank + - dot + custom-order: true + gofumpt: + module-path: github.com/nginx/agent + extra-rules: true + exclusions: + generated: lax + paths: + - .*gen.go + - .pb.go + - .pb.validate.go + - .*/generated_[A-Za-z_]*\.go + - .*fakes + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile.tools b/Makefile.tools index abb037868..512a729a2 100644 --- a/Makefile.tools +++ b/Makefile.tools @@ -1,6 +1,6 @@ OAPICODEGEN = github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@v2.1.0 LEFTHOOK = github.com/evilmartians/lefthook@v1.6.9 -GOLANGCILINT = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8 +GOLANGCILINT = github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1 PROTOCGENGO = google.golang.org/protobuf/cmd/protoc-gen-go@v1.32.0 GOFUMPT = mvdan.cc/gofumpt@v0.6.0 COUNTERFEITER = github.com/maxbrunsfeld/counterfeiter/v6@v6.8.1 diff --git a/go.mod b/go.mod index e84730f75..1f957f76f 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/nginx/agent/v3 -go 1.23.7 +go 1.24.0 -toolchain go1.23.10 +toolchain go1.24.4 require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1 diff --git a/internal/collector/nginxossreceiver/factory_test.go b/internal/collector/nginxossreceiver/factory_test.go index 9f64e3511..a48c3940d 100644 --- a/internal/collector/nginxossreceiver/factory_test.go +++ b/internal/collector/nginxossreceiver/factory_test.go @@ -23,7 +23,7 @@ import ( func TestType(t *testing.T) { factory := NewFactory() ft := factory.Type() - require.EqualValues(t, metadata.Type, ft) + require.Equal(t, metadata.Type, ft) } func TestValidConfig(t *testing.T) { diff --git a/internal/collector/nginxossreceiver/internal/scraper/accesslog/operator/input/file/config_test.go b/internal/collector/nginxossreceiver/internal/scraper/accesslog/operator/input/file/config_test.go index 8fc2040e2..70ee83087 100644 --- a/internal/collector/nginxossreceiver/internal/scraper/accesslog/operator/input/file/config_test.go +++ b/internal/collector/nginxossreceiver/internal/scraper/accesslog/operator/input/file/config_test.go @@ -27,7 +27,7 @@ func TestNewConfig(t *testing.T) { config := NewConfig() assert.NotNil(t, config) - assert.Equal(t, "access_log_file_input", config.InputConfig.OperatorID) + assert.Equal(t, "access_log_file_input", config.OperatorID) } func TestConfig_Build(t *testing.T) { diff --git a/internal/collector/otel_collector_plugin.go b/internal/collector/otel_collector_plugin.go index 18c101818..ec83790e7 100644 --- a/internal/collector/otel_collector_plugin.go +++ b/internal/collector/otel_collector_plugin.go @@ -436,7 +436,7 @@ func (oc *Collector) checkForNewReceivers(ctx context.Context, nginxConfigContex reloadCollector = true } } else { - slog.Debug("NAP logs feature disabled", "enabled_features", oc.config.Features) + slog.DebugContext(ctx, "NAP logs feature disabled", "enabled_features", oc.config.Features) } return reloadCollector diff --git a/internal/datasource/config/nginx_config_parser.go b/internal/datasource/config/nginx_config_parser.go index 949deb781..837f333a1 100644 --- a/internal/datasource/config/nginx_config_parser.go +++ b/internal/datasource/config/nginx_config_parser.go @@ -705,11 +705,12 @@ func (ncp *NginxConfigParser) parseListenDirective( } func (ncp *NginxConfigParser) parseListenHostAndPort(listenHost, listenPort string) (hostname, port string) { - if listenHost == "*" || listenHost == "" { + switch listenHost { + case "*", "": hostname = "127.0.0.1" - } else if listenHost == "::" || listenHost == "::1" { + case "::", "::1": hostname = "[::1]" - } else { + default: hostname = listenHost } port = listenPort diff --git a/internal/datasource/config/nginx_config_parser_benchmark_test.go b/internal/datasource/config/nginx_config_parser_benchmark_test.go index e61fb2380..74e1e549b 100644 --- a/internal/datasource/config/nginx_config_parser_benchmark_test.go +++ b/internal/datasource/config/nginx_config_parser_benchmark_test.go @@ -8,7 +8,6 @@ package config import ( "context" "fmt" - "io" "log/slog" "path/filepath" "testing" @@ -29,7 +28,7 @@ var configFilePaths = []string{ func BenchmarkNginxConfigParser_Parse(b *testing.B) { // Discard log messages - slog.SetDefault(slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{}))) + slog.SetDefault(slog.New(slog.DiscardHandler)) ctx := context.Background() agentConfig := types.AgentConfig() @@ -67,7 +66,7 @@ func BenchmarkNginxConfigParser_Parse(b *testing.B) { // These tests don't exercise the traversal very well, they are more to track the growth of configs in size func BenchmarkNginxConfigParserGeneratedConfig_Parse(b *testing.B) { - slog.SetDefault(slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{}))) + slog.SetDefault(slog.New(slog.DiscardHandler)) ctx := context.Background() agentConfig := types.AgentConfig() diff --git a/internal/datasource/config/nginx_config_parser_test.go b/internal/datasource/config/nginx_config_parser_test.go index 1474fce06..db6d0b6ff 100644 --- a/internal/datasource/config/nginx_config_parser_test.go +++ b/internal/datasource/config/nginx_config_parser_test.go @@ -529,7 +529,7 @@ func TestNginxConfigParser_Parse(t *testing.T) { assert.ElementsMatch(t, test.expectedConfigContext.ErrorLogs, result.ErrorLogs) assert.Equal(t, test.expectedConfigContext.StubStatus, result.StubStatus) assert.Equal(t, test.expectedConfigContext.InstanceID, result.InstanceID) - assert.Equal(t, len(test.expectedConfigContext.Files), len(result.Files)) + assert.Len(t, result.Files, len(test.expectedConfigContext.Files)) }) } } diff --git a/internal/file/file_manager_service.go b/internal/file/file_manager_service.go index b8076fdfb..d536e86dc 100644 --- a/internal/file/file_manager_service.go +++ b/internal/file/file_manager_service.go @@ -221,7 +221,7 @@ func (fms *FileManagerService) executeFileActions(ctx context.Context) error { for _, fileAction := range fms.fileActions { switch fileAction.Action { case model.Delete: - slog.Debug("File action, deleting file", "file", fileAction.File.GetFileMeta().GetName()) + slog.DebugContext(ctx, "File action, deleting file", "file", fileAction.File.GetFileMeta().GetName()) if err := os.Remove(fileAction.File.GetFileMeta().GetName()); err != nil && !os.IsNotExist(err) { return fmt.Errorf("error deleting file: %s error: %w", fileAction.File.GetFileMeta().GetName(), err) @@ -229,7 +229,7 @@ func (fms *FileManagerService) executeFileActions(ctx context.Context) error { continue case model.Add, model.Update: - slog.Debug("File action, add or update file", "file", fileAction.File.GetFileMeta().GetName()) + slog.DebugContext(ctx, "File action, add or update file", "file", fileAction.File.GetFileMeta().GetName()) updateErr := fms.fileUpdate(ctx, fileAction.File) if updateErr != nil { return updateErr diff --git a/internal/file/file_service_operator.go b/internal/file/file_service_operator.go index 6bf835fa0..ba8edb9c1 100644 --- a/internal/file/file_service_operator.go +++ b/internal/file/file_service_operator.go @@ -183,7 +183,7 @@ func (fso *FileServiceOperator) UpdateOverview( slog.DebugContext(newCtx, "UpdateOverview response", "response", response) if response.GetOverview() == nil { - slog.Debug("UpdateOverview response is empty") + slog.DebugContext(ctx, "UpdateOverview response is empty") return nil } delta := files.ConvertToMapOfFiles(response.GetOverview().GetFiles()) @@ -211,7 +211,7 @@ func (fso *FileServiceOperator) updateFiles( } iteration++ - slog.Info("Updating file overview after file updates", "attempt_number", iteration) + slog.InfoContext(ctx, "Updating file overview after file updates", "attempt_number", iteration) return fso.UpdateOverview(ctx, instanceID, diffFiles, iteration) } diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 1fcdbe216..01d0a506d 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -154,7 +154,8 @@ func CorrelationIDAttr(ctx context.Context) slog.Attr { value, ok := ctx.Value(CorrelationIDContextKey).(slog.Attr) if !ok { correlationID := GenerateCorrelationID() - slog.Debug( + slog.DebugContext( + ctx, "Correlation ID not found in context, generating new correlation ID", "correlation_id", correlationID) diff --git a/internal/plugin/plugin_manager_test.go b/internal/plugin/plugin_manager_test.go index 53fe3663b..172cb1542 100644 --- a/internal/plugin/plugin_manager_test.go +++ b/internal/plugin/plugin_manager_test.go @@ -147,7 +147,7 @@ func TestLoadPlugins(t *testing.T) { t.Run(test.name, func(tt *testing.T) { t.Logf("running test %s", test.name) result := LoadPlugins(ctx, test.input) - assert.Equal(tt, len(test.expected), len(result)) + assert.Len(tt, result, len(test.expected)) for i, expectedPlugin := range test.expected { assert.IsType(tt, expectedPlugin, result[i]) } diff --git a/internal/resource/nginx_instance_operator.go b/internal/resource/nginx_instance_operator.go index 70fb3af0e..1765e5c91 100644 --- a/internal/resource/nginx_instance_operator.go +++ b/internal/resource/nginx_instance_operator.go @@ -92,7 +92,7 @@ func (i *NginxInstanceOperator) Reload(ctx context.Context, instance *mpi.Instan slog.InfoContext(ctx, "Message received in logErrorChannel", "error", logErr) if logErr != nil { errorsFound = errors.Join(errorsFound, logErr) - slog.Info("Errors Found", "", errorsFound) + slog.InfoContext(ctx, "Errors Found", "", errorsFound) } } diff --git a/internal/resource/resource_plugin.go b/internal/resource/resource_plugin.go index 940a4f247..32ec56606 100644 --- a/internal/resource/resource_plugin.go +++ b/internal/resource/resource_plugin.go @@ -228,7 +228,8 @@ func (r *Resource) handleWriteConfigSuccessful(ctx context.Context, msg *bus.Mes configContext, err := r.resourceService.ApplyConfig(ctx, data.InstanceID) if err != nil { data.Error = err - slog.Error("errors found during config apply, sending error status, rolling back config", "err", err) + slog.ErrorContext(ctx, "errors found during config apply, "+ + "sending error status, rolling back config", "err", err) dpResponse := response.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_ERROR, "Config apply failed, rolling back config", data.InstanceID, err.Error()) r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: dpResponse}) @@ -259,7 +260,7 @@ func (r *Resource) handleRollbackWrite(ctx context.Context, msg *bus.Message) { } _, err := r.resourceService.ApplyConfig(ctx, data.InstanceID) if err != nil { - slog.Error("errors found during rollback, sending failure status", "err", err) + slog.ErrorContext(ctx, "errors found during rollback, sending failure status", "err", err) rollbackResponse := response.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_ERROR, "Rollback failed", data.InstanceID, err.Error()) diff --git a/internal/resource/resource_plugin_test.go b/internal/resource/resource_plugin_test.go index 9af07e9ca..e6651b46f 100644 --- a/internal/resource/resource_plugin_test.go +++ b/internal/resource/resource_plugin_test.go @@ -879,7 +879,7 @@ func TestResource_Process_Rollback(t *testing.T) { return messagePipe.Messages()[i].Topic < messagePipe.Messages()[j].Topic }) - assert.Equal(tt, len(test.topic), len(messagePipe.Messages())) + assert.Len(tt, messagePipe.Messages(), len(test.topic)) assert.Equal(t, test.topic[0], messagePipe.Messages()[0].Topic) diff --git a/internal/resource/resource_service.go b/internal/resource/resource_service.go index feb16263a..ed41c48a2 100644 --- a/internal/resource/resource_service.go +++ b/internal/resource/resource_service.go @@ -227,7 +227,7 @@ func (r *ResourceService) GetHTTPUpstreamServers(ctx context.Context, instance * servers, getServersErr := plusClient.GetHTTPServers(ctx, upstream) - slog.Warn("Error returned from NGINX Plus client, GetHTTPUpstreamServers", "err", getServersErr) + slog.WarnContext(ctx, "Error returned from NGINX Plus client, GetHTTPUpstreamServers", "err", getServersErr) return servers, createPlusAPIError(getServersErr) } @@ -242,7 +242,7 @@ func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instan servers, getUpstreamsErr := plusClient.GetUpstreams(ctx) - slog.Warn("Error returned from NGINX Plus client, GetUpstreams", "err", getUpstreamsErr) + slog.WarnContext(ctx, "Error returned from NGINX Plus client, GetUpstreams", "err", getUpstreamsErr) return servers, createPlusAPIError(getUpstreamsErr) } @@ -257,7 +257,7 @@ func (r *ResourceService) GetStreamUpstreams(ctx context.Context, instance *mpi. streamUpstreams, getServersErr := plusClient.GetStreamUpstreams(ctx) - slog.Warn("Error returned from NGINX Plus client, GetStreamUpstreams", "err", getServersErr) + slog.WarnContext(ctx, "Error returned from NGINX Plus client, GetStreamUpstreams", "err", getServersErr) return streamUpstreams, createPlusAPIError(getServersErr) } @@ -277,7 +277,7 @@ func (r *ResourceService) UpdateStreamServers(ctx context.Context, instance *mpi added, updated, deleted, updateError := plusClient.UpdateStreamServers(ctx, upstream, servers) - slog.Warn("Error returned from NGINX Plus client, UpdateStreamServers", "err", updateError) + slog.WarnContext(ctx, "Error returned from NGINX Plus client, UpdateStreamServers", "err", updateError) return added, updated, deleted, createPlusAPIError(updateError) } @@ -298,7 +298,7 @@ func (r *ResourceService) UpdateHTTPUpstreamServers(ctx context.Context, instanc added, updated, deleted, updateError := plusClient.UpdateHTTPServers(ctx, upstream, servers) if updateError != nil { - slog.Warn("Error returned from NGINX Plus client, UpdateHTTPUpstreamServers", "err", updateError) + slog.WarnContext(ctx, "Error returned from NGINX Plus client, UpdateHTTPUpstreamServers", "err", updateError) } return added, updated, deleted, createPlusAPIError(updateError) diff --git a/internal/watcher/instance/instance_watcher_service.go b/internal/watcher/instance/instance_watcher_service.go index d384a4f22..1bc50c496 100644 --- a/internal/watcher/instance/instance_watcher_service.go +++ b/internal/watcher/instance/instance_watcher_service.go @@ -115,7 +115,7 @@ func (iw *InstanceWatcherService) Watch( if iw.enabled.Load() { iw.checkForUpdates(ctx) } else { - slog.Debug("Skipping check for instance updates, instance watcher is disabled") + slog.DebugContext(ctx, "Skipping check for instance updates, instance watcher is disabled") } } } diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 2f20efdcc..b9ad448e6 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -136,16 +136,16 @@ func (w *NginxAppProtectInstanceWatcher) addWatcher(ctx context.Context, version } func (w *NginxAppProtectInstanceWatcher) readVersionFile(ctx context.Context, versionFile string) { - switch { - case versionFile == versionFilePath: + switch versionFile { + case versionFilePath: w.version = w.readFile(ctx, versionFilePath) - case versionFile == releaseFilePath: + case releaseFilePath: w.release = w.readFile(ctx, releaseFilePath) - case versionFile == threatCampaignVersionFilePath: + case threatCampaignVersionFilePath: w.threatCampaignVersion = w.readFile(ctx, threatCampaignVersionFilePath) - case versionFile == enforcerEngineVersionFilePath: + case enforcerEngineVersionFilePath: w.enforcerEngineVersion = w.readFile(ctx, enforcerEngineVersionFilePath) - case versionFile == attackSignatureVersionFilePath: + case attackSignatureVersionFilePath: w.attackSignatureVersion = w.readFile(ctx, attackSignatureVersionFilePath) } } diff --git a/internal/watcher/instance/nginx_process_parser_test.go b/internal/watcher/instance/nginx_process_parser_test.go index fe0c29d81..c2e204628 100644 --- a/internal/watcher/instance/nginx_process_parser_test.go +++ b/internal/watcher/instance/nginx_process_parser_test.go @@ -185,7 +185,7 @@ func TestNginxProcessParser_Parse(t *testing.T) { } } - assert.Equal(tt, len(test.expected), len(result)) + assert.Len(tt, result, len(test.expected)) }) } } @@ -391,7 +391,7 @@ func TestNginxProcessParser_Parse_Processes(t *testing.T) { assert.True(tt, proto.Equal(test.expected[id], instance)) } - assert.Equal(tt, len(test.expected), len(result)) + assert.Len(tt, result, len(test.expected)) }) } } @@ -622,8 +622,8 @@ func TestGetConfigPathFromCommand(t *testing.T) { assert.Equal(t, "/tmp/nginx.conf", result) result = confPathFromCommand("nginx: master process nginx -c") - assert.Equal(t, "", result) + assert.Empty(t, result) result = confPathFromCommand("") - assert.Equal(t, "", result) + assert.Empty(t, result) } diff --git a/pkg/id/uuid.go b/pkg/id/uuid.go index 043b7a534..efaf118f1 100644 --- a/pkg/id/uuid.go +++ b/pkg/id/uuid.go @@ -28,8 +28,14 @@ import ( // // A string representation of the generated UUID. func Generate(format string, a ...interface{}) string { + // need to set a default to avoid non-constant format string in call + f := "" + if format != "" { + f = format + } + h := sha256.New() - s := fmt.Sprintf(format, a...) + s := fmt.Sprintf(f, a...) _, _ = h.Write([]byte(s)) id := fmt.Sprintf("%x", h.Sum(nil)) diff --git a/scripts/packages/packager/Dockerfile b/scripts/packages/packager/Dockerfile index 51be5e23a..8353d7578 100644 --- a/scripts/packages/packager/Dockerfile +++ b/scripts/packages/packager/Dockerfile @@ -1,6 +1,6 @@ ARG package_type -FROM docker.io/golang:1.23-bullseye AS base +FROM docker.io/golang:1.24-bullseye AS base ARG PKG_VER="1.17.5" ARG PKG_DIR="/tmp/pkg" diff --git a/test/helpers/go_utils_test.go b/test/helpers/go_utils_test.go index 2caab7090..fa5fc1f40 100644 --- a/test/helpers/go_utils_test.go +++ b/test/helpers/go_utils_test.go @@ -13,7 +13,7 @@ import ( ) func TestGoVersion(t *testing.T) { - expected := "1.23.0" + expected := "1.24.0" actual, err := GoVersion(t, 2) diff --git a/test/helpers/os_utils_test.go b/test/helpers/os_utils_test.go index b7d601580..2ce93d558 100644 --- a/test/helpers/os_utils_test.go +++ b/test/helpers/os_utils_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -// nolint: stylecheck +// nolint: staticcheck func TestRemoveASCIIControlSignals(t *testing.T) { tests := []struct { name string diff --git a/test/mock/grpc/mock_management_command_service.go b/test/mock/grpc/mock_management_command_service.go index 3cae35f43..e360f8931 100644 --- a/test/mock/grpc/mock_management_command_service.go +++ b/test/mock/grpc/mock_management_command_service.go @@ -109,12 +109,12 @@ func (cs *CommandService) CreateConnection( } func (cs *CommandService) UpdateDataPlaneStatus( - _ context.Context, + ctx context.Context, request *mpi.UpdateDataPlaneStatusRequest) ( *mpi.UpdateDataPlaneStatusResponse, error, ) { - slog.Debug("Update data plane status request", "request", request) + slog.DebugContext(ctx, "Update data plane status request", "request", request) if request == nil { return nil, errors.New("empty update data plane status request") @@ -128,12 +128,12 @@ func (cs *CommandService) UpdateDataPlaneStatus( } func (cs *CommandService) UpdateDataPlaneHealth( - _ context.Context, + ctx context.Context, request *mpi.UpdateDataPlaneHealthRequest) ( *mpi.UpdateDataPlaneHealthResponse, error, ) { - slog.Debug("Update data plane health request", "request", request) + slog.DebugContext(ctx, "Update data plane health request", "request", request) if request == nil { return nil, errors.New("empty update dataplane health request") diff --git a/test/mock/grpc/mock_management_file_service.go b/test/mock/grpc/mock_management_file_service.go index d57e4e0d4..593c6abe6 100644 --- a/test/mock/grpc/mock_management_file_service.go +++ b/test/mock/grpc/mock_management_file_service.go @@ -54,15 +54,15 @@ func NewFileService(configDirectory string, requestChan chan *v1.ManagementPlane } func (mgs *FileService) GetOverview( - _ context.Context, + ctx context.Context, request *v1.GetOverviewRequest, ) (*v1.GetOverviewResponse, error) { configVersion := request.GetConfigVersion() - slog.Info("Getting overview", "config_version", configVersion) + slog.InfoContext(ctx, "Getting overview", "config_version", configVersion) if _, ok := mgs.instanceFiles[request.GetConfigVersion().GetInstanceId()]; !ok { - slog.Error("Config version not found", "config_version", configVersion) + slog.ErrorContext(ctx, "Config version not found", "config_version", configVersion) return nil, status.Errorf(codes.NotFound, "Config version not found") } @@ -76,7 +76,7 @@ func (mgs *FileService) GetOverview( // nolint: unparam func (mgs *FileService) UpdateOverview( - _ context.Context, + ctx context.Context, request *v1.UpdateOverviewRequest, ) (*v1.UpdateOverviewResponse, error) { overview := request.GetOverview() @@ -85,7 +85,7 @@ func (mgs *FileService) UpdateOverview( if errMarshaledJSON != nil { return nil, fmt.Errorf("failed to marshal struct back to JSON: %w", errMarshaledJSON) } - slog.Info("Updating overview JSON", "overview", marshaledJSON) + slog.InfoContext(ctx, "Updating overview JSON", "overview", marshaledJSON) mgs.instanceFiles[overview.GetConfigVersion().GetInstanceId()] = overview.GetFiles() @@ -107,24 +107,24 @@ func (mgs *FileService) UpdateOverview( } func (mgs *FileService) GetFile( - _ context.Context, + ctx context.Context, request *v1.GetFileRequest, ) (*v1.GetFileResponse, error) { fileName := request.GetFileMeta().GetName() fileHash := request.GetFileMeta().GetHash() - slog.Info("Getting file", "name", fileName, "hash", fileHash) + slog.InfoContext(ctx, "Getting file", "name", fileName, "hash", fileHash) fullFilePath := mgs.findFile(request.GetFileMeta()) if fullFilePath == "" { - slog.Error("File not found", "file_name", fileName) + slog.ErrorContext(ctx, "File not found", "file_name", fileName) return nil, status.Errorf(codes.NotFound, "File not found") } bytes, err := os.ReadFile(fullFilePath) if err != nil { - slog.Error("Failed to get file contents", "full_file_path", fullFilePath, "error", err) + slog.ErrorContext(ctx, "Failed to get file contents", "full_file_path", fullFilePath, "error", err) return nil, status.Errorf(codes.Internal, "Failed to get file contents") } @@ -271,7 +271,7 @@ func (mgs *FileService) sendGetFileStreamChunk(ctx context.Context, chunk v1.Fil }) validatedError := internalgrpc.ValidateGrpcError(err) if validatedError != nil { - slog.Error("Failed to send get file stream chunk", "error", validatedError) + slog.ErrorContext(ctx, "Failed to send get file stream chunk", "error", validatedError) return validatedError } @@ -313,7 +313,7 @@ func readChunk( } func (mgs *FileService) UpdateFile( - _ context.Context, + ctx context.Context, request *v1.UpdateFileRequest, ) (*v1.UpdateFileResponse, error) { fileContents := request.GetContents().GetContents() @@ -322,21 +322,21 @@ func (mgs *FileService) UpdateFile( fileHash := fileMeta.GetHash() filePermissions := fileMeta.GetPermissions() - slog.Info("Updating file", "name", fileName, "hash", fileHash) + slog.InfoContext(ctx, "Updating file", "name", fileName, "hash", fileHash) fullFilePath := mgs.findFile(request.GetFile().GetFileMeta()) if _, err := os.Stat(fullFilePath); os.IsNotExist(err) { statErr := os.MkdirAll(filepath.Dir(fullFilePath), os.ModePerm) if statErr != nil { - slog.Info("Failed to create/update file", "full_file_path", fullFilePath, "error", statErr) + slog.InfoContext(ctx, "Failed to create/update file", "full_file_path", fullFilePath, "error", statErr) return nil, status.Errorf(codes.Internal, "Failed to create/update file") } } err := os.WriteFile(fullFilePath, fileContents, fileMode(filePermissions)) if err != nil { - slog.Info("Failed to create/update file", "full_file_path", fullFilePath, "error", err) + slog.InfoContext(ctx, "Failed to create/update file", "full_file_path", fullFilePath, "error", err) return nil, status.Errorf(codes.Internal, "Failed to create/update file") } From 5d519568f01283c5f73c492f91c45c1ad456a59a Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Wed, 9 Jul 2025 15:47:20 +0100 Subject: [PATCH 02/12] add paths for NAP upon instance discovery --- .golangci.yml | 1 + .../instance/nginx-app-protect-instance-watcher.go | 2 ++ .../instance/nginx-app-protect-instance-watcher_test.go | 9 ++++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 020a7ff63..5648894d8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -340,6 +340,7 @@ linters-settings: - google.golang.org/grpc/credentials - github.com/testcontainers/testcontainers-go - google.golang.org/grpc + - github.com/nginx/agent/v3/api/grpc/mpi lll: # Max line length, lines longer will be reported. # '\t' is counted as 1 character by default, and can be changed with the tab-width option. diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 2f20efdcc..695403660 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -20,6 +20,7 @@ import ( ) var ( + napDirPath = "/opt/app_protect" versionFilePath = "/opt/app_protect/VERSION" releaseFilePath = "/opt/app_protect/RELEASE" attackSignatureVersionFilePath = "/opt/app_protect/var/update_files/signatures/version" @@ -49,6 +50,7 @@ type NginxAppProtectInstanceWatcher struct { } func NewNginxAppProtectInstanceWatcher(agentConfig *config.Config) *NginxAppProtectInstanceWatcher { + agentConfig.AllowedDirectories = append(agentConfig.AllowedDirectories, "/opt/app_protect") return &NginxAppProtectInstanceWatcher{ agentConfig: agentConfig, filesBeingWatched: make(map[string]bool), diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go b/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go index 48925663d..3d8d60302 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go @@ -8,6 +8,7 @@ package instance import ( "context" "os" + "slices" "testing" "time" @@ -95,6 +96,13 @@ func TestNginxAppProtectInstanceWatcher_Watch(t *testing.T) { }, ) + assert.True(t, + slices.Contains( + nginxAppProtectInstanceWatcher.agentConfig.AllowedDirectories, + napDirPath, + ), + ) + go nginxAppProtectInstanceWatcher.Watch(ctx, instancesChannel) t.Run("Test 1: New instance", func(t *testing.T) { @@ -112,7 +120,6 @@ func TestNginxAppProtectInstanceWatcher_Watch(t *testing.T) { t.Fatalf("Timed out waiting for instance updates") } }) - t.Run("Test 2: Update instance", func(t *testing.T) { _, err = enforcerEngineVersionFile.WriteAt([]byte("6.113.0"), 0) require.NoError(t, err) From 4c8f21b0242f6326fdf3c02210f68c80dd8d50cd Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Wed, 9 Jul 2025 18:35:31 +0100 Subject: [PATCH 03/12] use variable for NAP directory path --- internal/watcher/instance/nginx-app-protect-instance-watcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 695403660..6f74829ce 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -50,7 +50,7 @@ type NginxAppProtectInstanceWatcher struct { } func NewNginxAppProtectInstanceWatcher(agentConfig *config.Config) *NginxAppProtectInstanceWatcher { - agentConfig.AllowedDirectories = append(agentConfig.AllowedDirectories, "/opt/app_protect") + agentConfig.AllowedDirectories = append(agentConfig.AllowedDirectories, napDirPath) return &NginxAppProtectInstanceWatcher{ agentConfig: agentConfig, filesBeingWatched: make(map[string]bool), From dd96045a42337261bf97b750d4f003752d10aa9e Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Thu, 10 Jul 2025 11:26:03 +0100 Subject: [PATCH 04/12] add paths when creating NAP instance --- .../watcher/instance/nginx-app-protect-instance-watcher.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 6f74829ce..4834c47d8 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -50,7 +50,6 @@ type NginxAppProtectInstanceWatcher struct { } func NewNginxAppProtectInstanceWatcher(agentConfig *config.Config) *NginxAppProtectInstanceWatcher { - agentConfig.AllowedDirectories = append(agentConfig.AllowedDirectories, napDirPath) return &NginxAppProtectInstanceWatcher{ agentConfig: agentConfig, filesBeingWatched: make(map[string]bool), @@ -235,6 +234,8 @@ func (w *NginxAppProtectInstanceWatcher) createInstance(ctx context.Context) { } slog.InfoContext(ctx, "Discovered a new NGINX App Protect instance") + w.agentConfig.AllowedDirectories = append(w.agentConfig.AllowedDirectories, napDirPath) + slog.InfoContext(ctx, "Added NAP directory to allowed directories", "directories", w.agentConfig.AllowedDirectories) w.instancesChannel <- InstanceUpdatesMessage{ CorrelationID: logger.CorrelationIDAttr(ctx), From f36cac3c4285be76608659d7a27b59e492dac6db Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Fri, 11 Jul 2025 13:58:11 +0100 Subject: [PATCH 05/12] add nap paths by default, update agent config during upgrade --- internal/config/defaults.go | 2 ++ .../watcher/instance/nginx-app-protect-instance-watcher.go | 6 +----- scripts/packages/upgrade-agent-config.sh | 4 +++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 6c4a1ab3d..098361a3f 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -106,6 +106,8 @@ func DefaultAllowedDirectories() []string { "/usr/share/nginx/modules", "/var/run/nginx", "/var/log/nginx", + "/opt/app_protect", + "/etc/app_protect", } } diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 0eb1c42dd..64ae9baea 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -26,6 +26,7 @@ var ( attackSignatureVersionFilePath = "/opt/app_protect/var/update_files/signatures/version" threatCampaignVersionFilePath = "/opt/app_protect/var/update_files/threat_campaigns/version" enforcerEngineVersionFilePath = "/opt/app_protect/bd_config/enforcer.version" + napConfigPath = "/etc/app_protect" versionFiles = []string{ versionFilePath, @@ -232,11 +233,6 @@ func (w *NginxAppProtectInstanceWatcher) createInstance(ctx context.Context) { InstanceChildren: make([]*mpi.InstanceChild, 0), }, } - - slog.InfoContext(ctx, "Discovered a new NGINX App Protect instance") - w.agentConfig.AllowedDirectories = append(w.agentConfig.AllowedDirectories, napDirPath) - slog.InfoContext(ctx, "Added NAP directory to allowed directories", "directories", w.agentConfig.AllowedDirectories) - w.instancesChannel <- InstanceUpdatesMessage{ CorrelationID: logger.CorrelationIDAttr(ctx), InstanceUpdates: InstanceUpdates{ diff --git a/scripts/packages/upgrade-agent-config.sh b/scripts/packages/upgrade-agent-config.sh index 0a3fefe9f..9cc6e9bcc 100755 --- a/scripts/packages/upgrade-agent-config.sh +++ b/scripts/packages/upgrade-agent-config.sh @@ -52,7 +52,9 @@ for config_dir in $config_dirs; do done allowed_directories="${allowed_directories}\n - /var/log/nginx" - +allowed_directories="${allowed_directories}\n - /opt/app_protect" +allowed_directories="${allowed_directories}\n - /etc/app_protect" + v3_config_contents=" # # /etc/nginx-agent/nginx-agent.conf From bbd05e908ba5cd2b5cd6760c37095b463c4679d0 Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Fri, 11 Jul 2025 14:31:56 +0100 Subject: [PATCH 06/12] add nap by default --- internal/watcher/instance/nginx-app-protect-instance-watcher.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index 64ae9baea..a050ee449 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -20,13 +20,11 @@ import ( ) var ( - napDirPath = "/opt/app_protect" versionFilePath = "/opt/app_protect/VERSION" releaseFilePath = "/opt/app_protect/RELEASE" attackSignatureVersionFilePath = "/opt/app_protect/var/update_files/signatures/version" threatCampaignVersionFilePath = "/opt/app_protect/var/update_files/threat_campaigns/version" enforcerEngineVersionFilePath = "/opt/app_protect/bd_config/enforcer.version" - napConfigPath = "/etc/app_protect" versionFiles = []string{ versionFilePath, From 7124dc3d1e83183051557b664ac9f4b5e0f746eb Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Fri, 11 Jul 2025 14:40:20 +0100 Subject: [PATCH 07/12] nap paths to default agent configuration --- internal/config/config_test.go | 2 +- .../instance/nginx-app-protect-instance-watcher_test.go | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index f34fa9853..1062e721d 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -791,7 +791,7 @@ func agentConfig() *Config { }, AllowedDirectories: []string{ "/etc/nginx/", "/etc/nginx-agent/", "/usr/local/etc/nginx/", "/var/run/nginx/", "/var/log/nginx/", - "/usr/share/nginx/modules/", + "/usr/share/nginx/modules/", "/opt/app_protect/", "/etc/app_protect/", }, Collector: &Collector{ ConfigPath: "/etc/nginx-agent/nginx-agent-otelcol.yaml", diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go b/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go index 3d8d60302..2dae2d254 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher_test.go @@ -8,7 +8,6 @@ package instance import ( "context" "os" - "slices" "testing" "time" @@ -96,13 +95,6 @@ func TestNginxAppProtectInstanceWatcher_Watch(t *testing.T) { }, ) - assert.True(t, - slices.Contains( - nginxAppProtectInstanceWatcher.agentConfig.AllowedDirectories, - napDirPath, - ), - ) - go nginxAppProtectInstanceWatcher.Watch(ctx, instancesChannel) t.Run("Test 1: New instance", func(t *testing.T) { From a4a0602975007dd071192ca711543bff52b4f8e8 Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Mon, 14 Jul 2025 14:47:35 +0100 Subject: [PATCH 08/12] add back log message --- .../watcher/instance/nginx-app-protect-instance-watcher.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/watcher/instance/nginx-app-protect-instance-watcher.go b/internal/watcher/instance/nginx-app-protect-instance-watcher.go index a050ee449..b9ad448e6 100644 --- a/internal/watcher/instance/nginx-app-protect-instance-watcher.go +++ b/internal/watcher/instance/nginx-app-protect-instance-watcher.go @@ -231,6 +231,9 @@ func (w *NginxAppProtectInstanceWatcher) createInstance(ctx context.Context) { InstanceChildren: make([]*mpi.InstanceChild, 0), }, } + + slog.InfoContext(ctx, "Discovered a new NGINX App Protect instance") + w.instancesChannel <- InstanceUpdatesMessage{ CorrelationID: logger.CorrelationIDAttr(ctx), InstanceUpdates: InstanceUpdates{ From 457f3810e2c0a121a199d159bc051c6863a7dd17 Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Tue, 15 Jul 2025 14:56:54 +0100 Subject: [PATCH 09/12] only add config directory /etc/app_protect --- internal/config/config_test.go | 2 +- internal/config/defaults.go | 1 - scripts/packages/upgrade-agent-config.sh | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 1062e721d..3e2dbdabb 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -791,7 +791,7 @@ func agentConfig() *Config { }, AllowedDirectories: []string{ "/etc/nginx/", "/etc/nginx-agent/", "/usr/local/etc/nginx/", "/var/run/nginx/", "/var/log/nginx/", - "/usr/share/nginx/modules/", "/opt/app_protect/", "/etc/app_protect/", + "/usr/share/nginx/modules/", "/etc/app_protect/", }, Collector: &Collector{ ConfigPath: "/etc/nginx-agent/nginx-agent-otelcol.yaml", diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 098361a3f..160677472 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -106,7 +106,6 @@ func DefaultAllowedDirectories() []string { "/usr/share/nginx/modules", "/var/run/nginx", "/var/log/nginx", - "/opt/app_protect", "/etc/app_protect", } } diff --git a/scripts/packages/upgrade-agent-config.sh b/scripts/packages/upgrade-agent-config.sh index 9cc6e9bcc..4ea7f1582 100755 --- a/scripts/packages/upgrade-agent-config.sh +++ b/scripts/packages/upgrade-agent-config.sh @@ -52,7 +52,6 @@ for config_dir in $config_dirs; do done allowed_directories="${allowed_directories}\n - /var/log/nginx" -allowed_directories="${allowed_directories}\n - /opt/app_protect" allowed_directories="${allowed_directories}\n - /etc/app_protect" v3_config_contents=" From 35ca8cf0bd002c5fa0e86f8269ca16708342437b Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Tue, 15 Jul 2025 15:54:02 +0100 Subject: [PATCH 10/12] update preinstall.sh --- scripts/packages/preinstall.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/packages/preinstall.sh b/scripts/packages/preinstall.sh index 7bcc02250..530aa2706 100644 --- a/scripts/packages/preinstall.sh +++ b/scripts/packages/preinstall.sh @@ -109,6 +109,7 @@ labels: allowed_directories="${allowed_directories}\n - ${config_dir}" done allowed_directories="${allowed_directories}\n - /var/log/nginx" + allowed_directories="${allowed_directories}\n - /etc/app_protect" echo "Writing new v3 configuration to $v3_config_file" v3_config_contents=" From 26a02942116943db449dbeaa23e011a300811e47 Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Thu, 17 Jul 2025 11:04:47 +0100 Subject: [PATCH 11/12] update default config --- nginx-agent.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nginx-agent.conf b/nginx-agent.conf index b67980261..ae625f7cd 100644 --- a/nginx-agent.conf +++ b/nginx-agent.conf @@ -12,10 +12,12 @@ log: allowed_directories: - /etc/nginx + - /etc/app_protect - /usr/local/etc/nginx - /usr/share/nginx/modules - /var/run/nginx - /var/log/nginx + - # # Command server settings to connect to a management plane server # From 1bbc09144f25268d4ca3ed9cd6bd81c696737f16 Mon Sep 17 00:00:00 2001 From: Sean Breen Date: Thu, 17 Jul 2025 11:17:21 +0100 Subject: [PATCH 12/12] remove blank line --- nginx-agent.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/nginx-agent.conf b/nginx-agent.conf index ae625f7cd..559754f43 100644 --- a/nginx-agent.conf +++ b/nginx-agent.conf @@ -17,7 +17,6 @@ allowed_directories: - /usr/share/nginx/modules - /var/run/nginx - /var/log/nginx - - # # Command server settings to connect to a management plane server #