Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow snmp_context to be passed as optional parameter to override the snmp.ContextName #845

Closed
wants to merge 6 commits into from

Conversation

dszarmach
Copy link

@dszarmach dszarmach commented Feb 14, 2023

snmp?target=hostname&module=module will use existing c.Auth.ContextName from snmp.yml as g.ContextName if defined (same as previous behavior)

snmp?target=hostname&module=module&snmp_context=context_name allows for adding or overriding this value by passing it as a job param similar to target and module values.

this allows for simple automated configuration of jobs to scrape individual contexts without needing to define a new entry in snmp.yml for each

@SuperQ @RichiH

@RichiH
Copy link
Member

RichiH commented Feb 28, 2023 via email

@dszarmach
Copy link
Author

@RichiH wouldn't that only be a concern if someone was already re-using snmp v3 credentials across contexts improperly? A properly configured system aiming to do it securely would not have a single user with permissions to various contexts that were intended to be separated, so any attempt to redirect and re-use the credentials from "module_a,context_a" to "module_a,context_b" via snmp_exporter?snmp call would just generate an authentication failure, right?

@RichiH
Copy link
Member

RichiH commented Apr 28, 2023

I must have misunderstood this PR on mobile, sorry!

This seems fine, though it should probably be gated on being used with SNMPv3 only. The question is if the scrape should fail if there's a context for a v1/v2 auth block.

@bastischubert offered to test the PR against v3 hardware, I currently don't have access to any.

@RichiH
Copy link
Member

RichiH commented Apr 28, 2023

@dszarmach could you sign the DCO, please?

@dszarmach dszarmach force-pushed the main branch 2 times, most recently from eb10ef6 to bcf99ca Compare April 28, 2023 13:52
@dszarmach
Copy link
Author

@dszarmach could you sign the DCO, please?

Done

DCO
All commits are signed off!

@dszarmach
Copy link
Author

@bastischubert offered to test the PR against v3 hardware, I currently don't have access to any.

@bastischubert if you happen to be testing against cisco nxos for bgp:

add a mapping of context name to vrf like: snmp-server context bgp_vrf_1 vrf bgp_vrf_1

then you should see the following behavior:

snmp?module=bgp_v3&target=device_name = will return all bgp info not in a VRF
snmp?module=bgp_v3&target=device_name&snmp_context=bgp_vrf_1 = will return only bgp info for bgp_vrf_1 VRF

I have >200 contexts running this way in a production environment for the past 2 months without issue.

@bastischubert
Copy link
Member

@dszarmach
when building i get errors

[build@lbuild009 snmp_exporter]$ make
>> checking code style
gofmt checking failed!
diff ./collector/collector.go.orig ./collector/collector.go
--- ./collector/collector.go.orig
+++ ./collector/collector.go
@@ -158,7 +158,7 @@
 	}

 	// Configure auth.
-	config.WalkParams.ConfigureSNMP(&snmp,snmp_context)
+	config.WalkParams.ConfigureSNMP(&snmp, snmp_context)

 	// Do the actual walk.
 	err := snmp.Connect()
@@ -259,11 +259,11 @@
 }

 type collector struct {
-	ctx    context.Context
-	target string
-        snmp_context string
-	module *config.Module
-	logger log.Logger
+	ctx          context.Context
+	target       string
+	snmp_context string
+	module       *config.Module
+	logger       log.Logger
 }

 func New(ctx context.Context, target string, snmp_context string, module *config.Module, logger log.Logger) *collector {
diff ./config/config.go.orig ./config/config.go
--- ./config/config.go.orig
+++ ./config/config.go
@@ -125,7 +125,7 @@
 }

 // ConfigureSNMP sets the various version and auth settings.
-func (c WalkParams) ConfigureSNMP(g *gosnmp.GoSNMP,snmp_context string) {
+func (c WalkParams) ConfigureSNMP(g *gosnmp.GoSNMP, snmp_context string) {
 	switch c.Version {
 	case 1:
 		g.Version = gosnmp.Version1
@@ -135,11 +135,11 @@
 		g.Version = gosnmp.Version3
 	}
 	g.Community = string(c.Auth.Community)
-        if snmp_context == ""{
-	        g.ContextName = c.Auth.ContextName
-        } else{
-                g.ContextName = snmp_context
-        }
+	if snmp_context == "" {
+		g.ContextName = c.Auth.ContextName
+	} else {
+		g.ContextName = snmp_context
+	}
 	// v3 security settings.
 	g.SecurityModel = gosnmp.UserSecurityModel
 	usm := &gosnmp.UsmSecurityParameters{
diff ./main.go.orig ./main.go
--- ./main.go.orig
+++ ./main.go
@@ -85,13 +85,12 @@
 		moduleName = "if_mib"
 	}

-
-        snmp_context := query.Get("snmp_context")
-        if len(query["snmp_context"]) > 1 {
-                http.Error(w, "'snmp_context' parameter must only be specified once", 400)
-                snmpRequestErrors.Inc()
-                return
-        }
+	snmp_context := query.Get("snmp_context")
+	if len(query["snmp_context"]) > 1 {
+		http.Error(w, "'snmp_context' parameter must only be specified once", 400)
+		snmpRequestErrors.Inc()
+		return
+	}

 	sc.RLock()
 	module, ok := (*(sc.C))[moduleName]

Please ensure you are using go version go1.19.8 linux/amd64 for formatting code.
make: *** [Makefile.common:112: common-style] Error 1

using go build it produces a binary that works as expected

@dszarmach: could you fix the formatting, after that i don't see a reason to not merge that PR

Signed-off-by: Douglas <[email protected]>
@dszarmach
Copy link
Author

@dszarmach: could you fix the formatting, after that i don't see a reason to not merge that PR

done

@bastischubert
Copy link
Member

LGTM

@RichiH could you or someone else from the team have also have a look (failing circleci test) and get this one merged?

@SuperQ
Copy link
Member

SuperQ commented May 4, 2023

I don't think we actually want to do this. Passing arbitrary strings into SNMP is dangerous.

We're refactoring the SNMP configuration in #859 so that SNMPv3 Context can be configured as part of the auth, simplifying the coniguration. Would that be sufficient?

@dszarmach
Copy link
Author

@SuperQ the reason I made this was a scale problem in addition to convenience. Having to create a new entry for every SNMP context for every module in snmp config file pushed me up against a failure eventually - something like "excessive aliasing" in the YML I think was the error. Without aliasing the snmp config file balloons to hundreds of megs and performance suffers.

Could adding some safety checks on the passed context name before passing on to SNMP work here and address security concerns?

@SuperQ
Copy link
Member

SuperQ commented May 4, 2023

Take a look at the linked PR, it's designed to eliminate that exact problem. By splitting the SNMP auth/community/etc from the walk module, it makes it much easier to configure.

I'm also planning to eventually support multiple config files, so walks and auths can be built and shipped sparately.

@dszarmach
Copy link
Author

Take a look at the linked PR, it's designed to eliminate that exact problem. By splitting the SNMP auth/community/etc from the walk module, it makes it much easier to configure.

@SuperQ Interesting. I will keep an eye on that and once it is merged will attempt to refactor my config generation tool to use the new system. If it solves the problem I was trying to fix here, will move to the new method and close this PR.

@SuperQ
Copy link
Member

SuperQ commented Jul 1, 2023

FYI, the config split is now merged.

Copy link
Member

@SuperQ SuperQ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be rebased against latest.

@@ -55,7 +55,7 @@ ifneq ($(shell which gotestsum),)
endif
endif

PROMU_VERSION ?= 0.13.0
PROMU_VERSION ?= 0.14.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not modify Makefile.common in this PR. We automatically manage this file.

@@ -115,7 +115,7 @@ type ScrapeResults struct {
retries uint64
}

func ScrapeTarget(ctx context.Context, target string, config *config.Module, logger log.Logger) (ScrapeResults, error) {
func ScrapeTarget(ctx context.Context, target string, snmp_context string, config *config.Module, logger log.Logger) (ScrapeResults, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go style does not use underscores for varibale names. Please follow the Go style guide.

Suggested change
func ScrapeTarget(ctx context.Context, target string, snmp_context string, config *config.Module, logger log.Logger) (ScrapeResults, error) {
func ScrapeTarget(ctx context.Context, target string, snmpContext string, config *config.Module, logger log.Logger) (ScrapeResults, error) {

@SuperQ
Copy link
Member

SuperQ commented Oct 3, 2023

Ping, are you still interested in this? Would you mind if someone else took over work on this feature?

@dszarmach
Copy link
Author

@SuperQ feel free to have someone else take a look - have not had time to confirm the config split change fully replaces the utility of this or not as it requires a rewrite of some other config generation code first to test. If this PR ends up merged I will not have to do any of that, so yes still interested the feature.

@SuperQ
Copy link
Member

SuperQ commented Oct 3, 2023

I realized we actually implemented context name support when we refactored the Auth/Module split. I don't think this change is necessary now as controlling context can now be done from the vastly simplified config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants