Skip to content

Allow git for snmp config file#877

Merged
i3149 merged 13 commits intomainfrom
allow-git-clone-ssh
Feb 23, 2026
Merged

Allow git for snmp config file#877
i3149 merged 13 commits intomainfrom
allow-git-clone-ssh

Conversation

@i3149
Copy link
Contributor

@i3149 i3149 commented Feb 17, 2026

KT_GIT_ACCESS_USERNAME=$USERNAME KT_GIT_ACCESS_TOKEN=$PERSONAL_ACCESS_TOKEN ./bin/ktranslate -snmp git://Users/pye/src/configtest/foo/snmp.yaml

Allow a system like this where the snmp.yaml file is pulled from a remote git repo. No need to have KT_GIT_ACCESS_TOKEN and KT_GIT_ACCESS_USERNAME defined if not needed.

Also allows KT_GIT_ACCESS_TOKEN to be defined when pulling snmp profiles from a private repo.

Closes #875 #869

New env vars to think about:

	KT_GIT_ACCESS_TOKEN  
	KT_GIT_ACCESS_USERNAME 
	KT_GIT_PULL_BRANCH     
	KT_GIT_PUSH_BRANCH 
        KT_GIT_COMMIT_EMAIL
        KT_GIT_COMMIT_NAME

Full use:

KT_GIT_PULL_BRANCH=pullbranch KT_GIT_PUSH_BRANCH=pushbranch KT_GIT_ACCESS_USERNAME=foo KT_GIT_ACCESS_TOKEN=XXX ./bin/ktranslate -snmp git://github.com/i3149/configtest/snmp.yaml -snmp_discovery

You can use these for the -snmp flag, -config flag and also the profile_git_url line in the snmp config file.

When KT_GIT_PULL_BRANCH is defined, this branch will be used to pull the config files from.
When KT_GIT_PUSH_BRANCH is defined, this branch will be used to push an updated snmp.yaml file on snmp discovery. NOTE This branch must exist on the remote repo. It will not be created.

KT_GIT_COMMIT_EMAIL defines the commiter email to use.
KT_GIT_COMMIT_NAME defines the commiter name.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for loading SNMP config (and MIB profiles) from git-backed sources, including optional GitHub token auth via KT_GITHUB_ACCESS_TOKEN.

Changes:

  • Add git:// scheme handling to SNMP util LoadFile/WriteFile.
  • Add BasicAuth support for cloning MIB profiles from git when a token is present.
  • Update Go module dependencies (notably introducing go-git/v6 and related transitive bumps).

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 8 comments.

File Description
pkg/inputs/snmp/util/file.go Adds git scheme support for config load/write via cloning a repo and reading a file.
pkg/inputs/snmp/mibs/git.go Adds token-based auth for cloning profile repositories.
go.mod Adds go-git/v6 and updates several dependency versions.
go.sum Updates dependency checksums in line with go.mod changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +45
case "git":
return loadFromGit(ctx, u)
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The new git:// scheme functionality in LoadFile and WriteFile is not covered by tests in file_test.go. Consider adding test cases for the git:// scheme to ensure the functionality works correctly and to prevent regressions. The test should verify URL parsing, authentication setup, and successful file retrieval.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 260 to 263
return "", nil, err
}

return filePath, r, err
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The error path on line 263 returns 'err' without context about which operation failed. While the gitClone function will fail at PlainCloneContext, it would be more helpful to wrap this error with additional context about the URL being cloned. Consider wrapping the error similar to the other error returns in this function.

Suggested change
return "", nil, err
}
return filePath, r, err
return "", nil, fmt.Errorf("failed to clone git repository %s: %w", gitRepo, err)
}
return filePath, r, nil

Copilot uses AI. Check for mistakes.
Comment on lines +206 to +209
// Push repo.
return r.Push(&git.PushOptions{
Auth: GetGitCreds(),
Force: true,
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Using Force: true in the PushOptions (line 209) is potentially dangerous as it will overwrite remote changes without regard to conflicts. This could cause data loss if multiple instances of ktranslate are running and trying to update the same file, or if manual changes were made to the repository.

Consider either:

  1. Removing Force: true and handling push conflicts gracefully
  2. Implementing a merge strategy to preserve remote changes
  3. At minimum, adding prominent documentation warning about this behavior and recommending that only one instance should have write access

This is particularly risky given the SNMP discovery use case where updates might happen automatically.

Suggested change
// Push repo.
return r.Push(&git.PushOptions{
Auth: GetGitCreds(),
Force: true,
// Push repo without forcing, to avoid overwriting remote changes unintentionally.
return r.Push(&git.PushOptions{
Auth: GetGitCreds(),

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +150
dir, err := os.MkdirTemp("", "ktrans")
if err != nil {
return err
}
defer os.RemoveAll(dir) // clean up
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

If the Git clone operation succeeds but a subsequent operation fails (e.g., reading the file, creating worktree, etc.), the deferred os.RemoveAll will still execute. However, if os.MkdirTemp itself fails and returns early, or if there's a panic before the defer is set up, the cleanup won't happen. While this is generally acceptable for temp directories, consider whether there are scenarios where credentials or sensitive data might remain in the temp directory that should be more aggressively cleaned up.

Copilot uses AI. Check for mistakes.
Comment on lines +247 to +258
cloneOpts := &git.CloneOptions{
URL: gitRepo,
Auth: GetGitCreds(),
Progress: io.Discard,
}
// If a branch is specified, clone that branch directly instead of
// cloning the default branch and manually rewriting references.
if branch != "" {
cloneOpts.ReferenceName = branch
cloneOpts.SingleBranch = true
}
r, err := git.PlainCloneContext(ctx, dir, cloneOpts)
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The temporary directory is created for each git operation but there's no timeout or size limit on the clone operation. A malicious or very large repository could potentially:

  1. Consume significant disk space in the temp directory
  2. Take a very long time to clone, blocking the operation

Consider adding:

  • A timeout on the clone context (derived from the passed ctx or with a reasonable default)
  • Size/depth limits in CloneOptions (e.g., Depth: 1 for shallow clone if only the latest version is needed)

This would improve resilience against denial-of-service scenarios and reduce resource consumption.

Copilot uses AI. Check for mistakes.
Comment on lines +214 to +228
func GetGitCreds() *githttp.BasicAuth {
token := os.Getenv(KT_GIT_ACCESS_TOKEN)
if token == "" {
return nil
}
username := os.Getenv(KT_GIT_ACCESS_USERNAME)
if username == "" {
// Many Git hosting services require a non-empty username when using personal access tokens.
// Default to a conventional placeholder username if none is provided via environment.
username = "git"
}
return &githttp.BasicAuth{
Username: username,
Password: token,
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Security concern: The Git credentials (password/token) will be exposed in memory as plain strings throughout the authentication process. Consider adding a security note in the documentation warning users that:

  1. Tokens should have minimal necessary permissions (read-only for pulling, write for pushing)
  2. Tokens should be rotated regularly
  3. Environment variables containing tokens should be properly secured in the deployment environment

While this is a common pattern for Git authentication, it's important to document the security implications for users.

Copilot uses AI. Check for mistakes.
repo = strings.TrimSuffix(repo, ".git")
}
gitRepo := "https://" + path.Join(url.Host, owner, repo) + ".git"
filePath := filepath.Clean(path.Join(segments[2:]...))
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

Security: The filepath.Clean call on line 245 helps prevent path traversal, but it doesn't fully protect against malicious paths. An attacker could craft a URL with segments like "../../../etc/passwd" which, after joining segments[2:], could potentially escape the intended directory. Consider validating that the resulting filePath doesn't contain ".." segments after cleaning, or ensure it stays within the cloned repository directory bounds.

Suggested change
filePath := filepath.Clean(path.Join(segments[2:]...))
filePath := filepath.Clean(path.Join(segments[2:]...))
// Security: ensure the cleaned filePath does not contain any path traversal components.
for _, seg := range strings.Split(filePath, string(os.PathSeparator)) {
if seg == ".." {
return "", nil, fmt.Errorf("invalid file path in git url (path traversal detected): %s", url.String())
}
}

Copilot uses AI. Check for mistakes.
if strings.HasSuffix(repo, ".git") {
repo = strings.TrimSuffix(repo, ".git")
}
gitRepo := "https://" + path.Join(url.Host, owner, repo) + ".git"
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The gitClone function constructs an HTTPS URL by joining path segments, but path.Join will clean the path and potentially remove important elements. For example, if url.Host contains a port (e.g., "github.com:443"), path.Join may not handle it correctly. Additionally, if the host contains special characters, they might not be properly escaped.

Consider using url.URL struct methods to build the Git URL more safely, or at minimum add validation that url.Host doesn't contain unexpected characters like slashes or ports.

Suggested change
gitRepo := "https://" + path.Join(url.Host, owner, repo) + ".git"
gitURL := &url.URL{
Scheme: "https",
Host: url.Host,
Path: path.Join("/", owner, repo) + ".git",
}
gitRepo := gitURL.String()

Copilot uses AI. Check for mistakes.
// LoadConfig returns a ktranslate configuration from the specified path
func LoadConfig(configPath string) (*Config, error) {
f, err := os.Open(configPath)
func LoadConfig(ctx context.Context, configPath string) (*Config, error) {
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The LoadConfig function signature has changed from LoadConfig(configPath string) to LoadConfig(ctx context.Context, configPath string). This is a breaking API change that will affect any external code that calls this function.

While the change is necessary to support context propagation for Git operations, this should be documented in release notes or migration guide. The PR correctly updates the main caller in cmd/ktranslate/main.go, but any external consumers of this package would need to update their code.

Copilot uses AI. Check for mistakes.
@i3149
Copy link
Contributor Author

i3149 commented Feb 23, 2026

New env vars to think about:

KT_GIT_ACCESS_TOKEN  
KT_GIT_ACCESS_USERNAME 
KT_GIT_PULL_BRANCH     
KT_GIT_PUSH_BRANCH 
    KT_GIT_COMMIT_EMAIL
    KT_GIT_COMMIT_NAME

Full use:

KT_GIT_PULL_BRANCH=pullbranch KT_GIT_PUSH_BRANCH=pushbranch KT_GIT_ACCESS_USERNAME=foo KT_GIT_ACCESS_TOKEN=XXX ./bin/ktranslate -snmp git://github.com/i3149/configtest/snmp.yaml -snmp_discovery
You can use these for the -snmp flag, -config flag and also the profile_git_url line in the snmp config file.

When KT_GIT_PULL_BRANCH is defined, this branch will be used to pull the config files from.
When KT_GIT_PUSH_BRANCH is defined, this branch will be used to push an updated snmp.yaml file on snmp discovery. NOTE This branch must exist on the remote repo. It will not be created.

KT_GIT_COMMIT_EMAIL defines the commiter email to use.
KT_GIT_COMMIT_NAME defines the commiter name.

@i3149 i3149 merged commit c7b9c7f into main Feb 23, 2026
1 check passed
@i3149 i3149 deleted the allow-git-clone-ssh branch February 23, 2026 22:52
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.

Allow snmp config file to be downloaded from a remote location.

2 participants