Class ::nsmcp::ConfigurationTool (public)
::nx::Class ::nsmcp::ConfigurationTool
Defined in /usr/local/ns/tcl/nsmcp/lib/config-tools.tcl
- Testcases:
- No testcase defined.
Source code: :property {name configuration} :property {permission diagnostics.runtime.read} :property redactor:required :property authorizer:required :property {description {Inspect live NaviServer configuration for configuration reviews, SMTP policy interpretation and scaling advice. scope=server (default) returns process-wide sections plus the authenticated virtual server's sections, excluding other virtual servers. scope=process returns every section across all virtual servers and requires diagnostics.configuration.process.read in addition to diagnostics.runtime.read. Includes driver, database-pool, connection-pool, limit, logging and module settings. Policy scripts are returned as data and are never executed. Named credential values and URI userinfo are redacted; referenced files are not read. Configuration reflects the current configuration table, including defaults published there by modules, not necessarily every compiled default or a historical policy. Use section to select an exact section and its descendants. Follow nextArguments to retrieve remaining sections. Pair with server_topology and server_runtime for actual installed components and utilization.}} :property {inputSchema {{} object {type string object properties object { scope object {type string string enum array {0 string server 1 string process} default string server} section object {type string string description string {Exact section prefix, including descendants; defaults to all authorized sections.}} limit object {type string integer minimum number 1 maximum number 100 default number 50} offset object {type string integer minimum number 0 default number 0} } additionalProperties boolean false}}} :method options {arguments} { if {[lindex $arguments 1] ne "object"} {error "Expected arguments object"} set result {scope server section {} limit 50 offset 0} foreach {key type value} [lindex $arguments 2] { switch -- $key { scope { if {$type ne "string" || $value ni {server process}} {error "scope must be server or process"} } section { if {$type ne "string" || [string length $value] > 512 || [regexp {[\x00\r\n]} $value]} {error "Invalid configuration section"} set value [string trimright $value /] } limit - offset { if {$type ne "number" || ![string is integer -strict $value] || $value < 0 || ($key eq "limit" && ($value < 1 || $value > 100))} {error "Invalid $key"} } default {error "Unknown argument: $key"} } dict set result $key $value } return $result } :public method validate {arguments} { if {[catch {:options $arguments} message]} { return -code error -errorcode {NSMCP RPC -32602} $message } } :method sections {} { set sections {} foreach handle [ns_configsections] { dict set sections [ns_set name $handle] [ns_set array $handle] } return $sections } :method credentialParameter {name} { return [regexp -nocase {(password|passwd|secret|token|credential|authorization|cookie|private[-_]?key)} $name] } :method value {name value secrets} { if {[:credentialParameter $name]} {return {[REDACTED]}} # Remove URI userinfo even for relay/datasource parameters and scripts. regsub -all {://[^/\s@]+@} $value {://[REDACTED]@} value # Database connection strings can carry credentials inside a datasource. regsub -all -nocase {(\m(?:password|passwd|secret|token|credential|authorization)\s*=\s*)(?:'[^']*'|"[^"]*"|[^\s;]+)} $value {\1[REDACTED]} value foreach secret $secrets { if {$value eq $secret} {return {[REDACTED]}} if {[string length $secret] >= 4} { set value [string map [list $secret {[REDACTED]}] $value] } } return [${:redactor} message $value] } :public method execute {context arguments} { set options [:options $arguments] set server [$context server] set scope [dict get $options scope] if {$scope eq "process"} { ${:authorizer} require $context diagnostics.configuration.process.read } set prefix [dict get $options section] set sections [:sections] set secrets {} dict for {section parameters} $sections { foreach {name value} $parameters { if {[:credentialParameter $name] && $value ne ""} {lappend secrets $value} } } set names {} set excluded 0 foreach section [lsort [dict keys $sections]] { if {$scope eq "server" && [string match ns/server/* $section] && $section ne "ns/server/$server" && [string first "ns/server/$server/" $section] != 0} { incr excluded continue } if {$prefix ne "" && $section ne $prefix && [string first $prefix/ $section] != 0} continue lappend names $section } set offset [dict get $options offset] set limit [dict get $options limit] set array {} set index 0 foreach section [lrange $names $offset [expr {$offset+$limit-1}]] { set parameters {} set parameterIndex 0 set seen {} foreach {name value} [dict get $sections $section] { set clean [:value $name $value $secrets] set folded [string tolower $name] lappend parameters $parameterIndex object [list name string $name value string $clean redacted boolean [expr {$clean ne $value}] firstOccurrence boolean [expr {$folded ni $seen}]] lappend seen $folded incr parameterIndex } set sectionScope [expr {[string first "ns/server/" $section] == 0 ? "server" : "process"}] lappend array $index object [list name string $section scope string $sectionScope parameters array $parameters] incr index } set more [expr {$offset+$index < [llength $names]}] set next {} if {$more} { set next [list scope string $scope section string $prefix limit number $limit offset number [expr {$offset+$index}]] } return [list {} object [list server string $server observedAt number [clock seconds] scope string $scope configurationFile string [ns_info config] sectionCount number [llength $names] excludedServerSections number $excluded sections array $array more boolean $more nextArguments object $next coverage object {historical boolean false referencedFilesRead boolean false compiledDefaultsComplete boolean false}]] }XQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)