Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
gopkg.in/relistan/rubberneck.v1
Pretty(ish) print configuration output on application startup! Make it easy to see what those env vars actually told your app to do!
It's recommended to use the gopkg.in service for this package since it means you'll always get a tagged release that maintains a stable API.
go get gopkg.in/relistan/rubberneck.v1
Modern applications are often configured from environment variables, or from a combination of environment variables and command line flags, or config files. Environment variables are great and they're recommended by everthing from The Twelve-Factor App to modern container engines.
This is good stuff. But there are a couple of challenges:
Env vars make it very easy to think you're configuring your app while
accidentally leaving out critial settings, or misspelling a variable, or
putting an extra _
where it wasn't needed. This can make debugging
problematic. What config was it actually using when it ran out of memory?
Discoverability is a challenge. One nice thing about config files is that they make it easy to see all the possible configuration settings in one place. You can ship your app with a default configuration with lots of comments in it and users can easily discover which settings to provide. If you configure your app with env vars, you have to put this all into the documentation (always a good idea, anyway), but you lose the direct tie between the code and the docs. That means it's easy to have settings that aren't in the docs.
In Go, configuration is usually stored in a struct or nested struct. This makes using systems like envconfig or Kingpin really easy. Having the configuration collected all together presents a possible solution:
One possibility is to print out your application's configuration on startup. Once all the configuration has been generated, all CLI flags applied, dump the struct to the stdout of the application so that we can see not just what env vars were passed, but what the configuration was that was actually generated inside the application. You can also see what defaults got applied, which overrides were taken into account, and exactly what was in the struct at startup time.
You could do this in a lot of ways. This is for humans and humans don't read JSON easily, but you could still dump a TOML or YAML file, for example. But the output won't nest easily into your logging system, for example. So Rubberneck tries to solve that in a really simple way.
You may always import this repo from GitHub, which will get you whatever is on the master branch. But I recommend using the gopkg.in service, which provides versioned repo support for the go tools. To get this package, I recommend:
go get gopkg.in/relistan/rubberneck.v1
To import it:
import "gopkg.in/relistan/rubberneck.v1"
The most basic usage is:
rubberneck.Print(myConfigStruct)
This will dump the output to stdout using the fmt
package and will look something
like:
Settings -----------------------------------------
* AdvertiseIP: 192.168.168.168
* ClusterIPs: [10.3.18.204 123.123.123.123]
* ConfigFile: sidecar.toml
* ClusterName: default
* CpuProfile: false
* Discover: [docker static]
* HAproxyDisable: false
* LoggingLevel:
* Sidecar:
* ExcludeIPs: [192.168.168.168]
* StatsAddr:
* PushPullInterval:
* Duration: 20s
* GossipMessages: 20
* LoggingFormat: standard
* LoggingLevel: debug
* DefaultCheckEndpoint:
* DockerDiscovery:
* DockerURL: unix:///var/run/docker.sock
--------------------------------------------------
If you want to instead print to the logrus
package you could do is like this:
printer := rubberneck.NewPrinter(log.Infof, rubberneck.NoAddLineFeed)
printer.Print(opts)
If you wanted to provide a custom label at the top, and to print out more than one struct you could do something like this:
printer := rubberneck.NewPrinter(log.Infof, rubberneck.NoAddLineFeed)
printer.PrintWithLabel("Sidecar starting", *opts, config)
This will result in the "Settings" block above being titled liked:
INFO[001] Sidecar starting ---------------------------------
INFO[001] * AdvertiseIP: 192.168.168.168
INFO[001] * ClusterIPs: [10.3.18.204 123.123.123.123]
INFO[001] * ConfigFile: sidecar.toml
How to handle output is highly configurable because Rubberneck just takes a function as the output argument. The function must be of the following definition:
type printerFunc func(format string, v ...interface{})
The various logrus functions conform to this as do those of various other packages. If yours doesn't, or you want to do something else with the output, you can pass an anonymous function that does what you need.
Printing configuration settings may also include some sensitive data that you might not want to see in your logs. This includes passwords, private keys etc. You can provide a masking function to filter out these values. For example:
var redacted = "[REDACTED]"
maskFunc := func(argument string) *string {
if argument == "Password" {
return &redacted
}
return nil
}
printer := rubberneck.NewPrinterWithKeyMasking(log.Printf, maskFunc, rubberneck.NoAddLineFeed)
printer.Print(opts)
The above masking will then mask the password setting:
Settings -----------------------------------------
* AdvertiseIP: 192.168.168.168
* ClusterIPs: [10.3.18.204 123.123.123.123]
* Password: [REDACTED]
--------------------------------------------------
This is for printing configuration structs, usually derived from environment variable configurations or CLI flags, and therefore does not attempt to handle all possible structures. It assumes that you don't have anything but basic types inside of slices, for example. This is generally what you want. If it's not, then you might be better off dumping out YAML or something more complex.
Contributions are more than welcome. Bug reports with specific reproduction steps are great. If you have a code contribution you'd like to make, open a pull request with suggested code.
Pull requests should:
Ping us to let us know you're working on something interesting by opening a GitHub Issue on the project.
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.