Skip to content
This repository was archived by the owner on Nov 26, 2024. It is now read-only.

Commit 5c03cd1

Browse files
authored
Added Memcachier support (#5)
1 parent 74ebea2 commit 5c03cd1

9 files changed

Lines changed: 203 additions & 22 deletions

File tree

README.md

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ This tool parses Go binary dependencies and calls [NVD database](https://nvd.nis
88
2. [Usage](#usage)
99
3. [Configuration](#configuration)
1010
4. [Cache](#cache)
11+
- [Memcachier](#memcachier)
12+
- [Memcached](#memcached)
13+
- [Memory](#memory)
1114
5. [Version](#versions)
1215
6. [How to Fix Vulnerabilities](#how-to-fix-vulnerabilities)
1316
7. [Data Source](#data-source)
@@ -46,7 +49,7 @@ Exit code is *1* if exposed vulnerabilities were found, *2* if there was an erro
4649
4750
You can pass *-verbose* option on command line to print vulnerability report, even if binary is not vulnerable and for all vulnerabilities, even if they are ignored or not exposed.
4851
49-
You can set *-strict* flag on command line so that vulnerabilities without version are considered matching vulnerability. In this case, you should check vulnerability manually and disable it in configuration file if necessary.
52+
You can set *-strict* flag on command line so that vulnerabilities without version are considered matching dependency version. In this case, you should check vulnerability manually and disable it in configuration file if necessary.
5053
5154
You can pass configuration file with *-config config.yml*, see configuration section below.
5255
@@ -63,6 +66,11 @@ Configuration file is in YAML format as follows:
6366
```yaml
6467
api-key: "28c6112c-a7bc-4a4e-9b14-75be6da02211"
6568
strict: false
69+
memcachier:
70+
address: mcx.cy.eu-central-1.ec2.memcachier.com:11211
71+
expiration: 86400
72+
username: foo
73+
password: bar
6674
memcached:
6775
address: 127.0.0.1:11211
6876
expiration: 86400
@@ -74,6 +82,7 @@ Configuration fields are the following:
7482

7583
- **api-key**: this is your NVD API key
7684
- **strict**: tells if we should consider vulnerability matches without version as matching dependency
85+
- **memcachier** is the configuration for *memcachier*, with **address**, **expiration** (time in seconds), **username** and **password**
7786
- **memcached** is the configuration for *memcached*, with **address** and **expiration** time in seconds
7887
- **ignore**: a list of CVE vulnerabilities to ignore
7988

@@ -83,9 +92,53 @@ Note that without API key, you will be limited to *10* requests in a rolling *60
8392

8493
## Cache
8594

86-
If you define the *memcached* configuration in your configuration file, *memcached* will be used to cache calls to NVD database. This is useful because if you perform more call that allowed, your calls will significantly slow down. An sample [docker-compose.yml](https://github.com/intercloud/gobinsec/blob/main/docker-compose.yml) to start a *memcached* instance is proposed in this project.
95+
A cache is useful because if you perform more call to NVD database that allowed, your calls will significantly slow down. Gobinsec tries to build caches in this order:
96+
97+
### Memcachier
98+
99+
A cache is built with *Memcachier* if following section is found in configuration file:
100+
101+
```yaml
102+
memcachier:
103+
address: ...
104+
expiration: ...
105+
username: ...
106+
password: ...
107+
```
108+
109+
Else, il will look for following environment variables:
110+
111+
```
112+
MEMCACHIER_ADDRESS
113+
MEMCACHIER_EXPIRATION
114+
MEMCACHIER_USERNAME
115+
MEMCACHIER_PASSWORD
116+
```
117+
118+
[Memcachier](https://www.memcachier.com) is an online cache provider with free tiers.
119+
120+
### Memcached
121+
122+
If no configuration is found for *Memcachier*, it will try to build a cache for *Memcached*, if following section is found in configuration file:
123+
124+
```yaml
125+
memcached:
126+
address: ...
127+
expiration: ...
128+
```
129+
130+
Else it will look for following environment variables:
131+
132+
```
133+
MEMCACHED_ADDRESS
134+
MEMCACHED_EXPIRATION
135+
```
136+
137+
A sample [docker-compose.yml](https://github.com/intercloud/gobinsec/blob/main/docker-compose.yml) file to start a *memcached* instance is provided in this project.
138+
139+
### Memory
87140

88-
If you don't define the *memcached* configuration, the program will use a memory cache when you pass more than one binary to analyse on command line.
141+
If no configuration is found for *Memcachier* and *Memcached*, it will instantiate a memory cache. This cache will be useful if you pass more than one binary on command line.
89142

90143
## Versions
91144

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ module github.com/intercloud/gobinsec
33
go 1.17
44

55
require (
6+
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d
67
github.com/fatih/color v1.13.0
8+
github.com/memcachier/gomemcache v0.0.0-20170425125614-d027381f7653
79
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
810
)
911

1012
require (
11-
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
1213
github.com/mattn/go-colorable v0.1.9 // indirect
1314
github.com/mattn/go-isatty v0.0.14 // indirect
1415
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
77
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
88
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
99
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
10+
github.com/memcachier/gomemcache v0.0.0-20170425125614-d027381f7653 h1:222emoxOt/bCmNHp8Xt0Pr5Am3gIbqRKFpb4CQ9O2SI=
11+
github.com/memcachier/gomemcache v0.0.0-20170425125614-d027381f7653/go.mod h1:KoYVbOQexD45AOLfn+gsFB6c3o4ANzP1QKzjE6tZbK0=
1012
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1113
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1214
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=

gobinsec/cache-memcached.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
11
package gobinsec
22

3-
import "github.com/bradfitz/gomemcache/memcache"
3+
import (
4+
"os"
5+
"strconv"
6+
7+
"github.com/bradfitz/gomemcache/memcache"
8+
)
9+
10+
// MemcachedConfig is the configuration for memcached
11+
type MemcachedConfig struct {
12+
Address string `yaml:"address"`
13+
Expiration int32 `yaml:"expiration"`
14+
}
15+
16+
// NewMemcachedConfig returns configuration
17+
func NewMemcachedConfig(config *MemcachedConfig) *MemcachedConfig {
18+
var address string
19+
var expiration int32
20+
if config != nil {
21+
return config
22+
} else if os.Getenv("MEMCACHED_ADDRESS") != "" {
23+
address = os.Getenv("MEMCACHED_ADDRESS")
24+
exp, err := strconv.Atoi(os.Getenv("MEMCACHED_EXPIRATION"))
25+
if err != nil {
26+
return nil
27+
}
28+
expiration = int32(exp)
29+
return &MemcachedConfig{
30+
Address: address,
31+
Expiration: expiration,
32+
}
33+
} else {
34+
return nil
35+
}
36+
}
437

538
// MemcachedClient is the Cache using memcached
639
type MemcachedClient struct {
@@ -9,10 +42,10 @@ type MemcachedClient struct {
942
}
1043

1144
// NewMemcachedCache builds a memcached cache
12-
func NewMemcachedCache() Cache {
45+
func NewMemcachedCache(config *MemcachedConfig) Cache {
1346
cache := MemcachedClient{
14-
Client: memcache.New(config.Memcached.Address),
15-
Expiration: config.Memcached.Expiration,
47+
Client: memcache.New(config.Address),
48+
Expiration: config.Expiration,
1649
}
1750
return &cache
1851
}

gobinsec/cache-memcachier.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package gobinsec
2+
3+
import (
4+
"os"
5+
"strconv"
6+
7+
"github.com/memcachier/gomemcache/memcache"
8+
)
9+
10+
// MemcachierConfig is the configuration for Memcachier
11+
type MemcachierConfig struct {
12+
Address string `yaml:"address"`
13+
Expiration int32 `yaml:"expiration"`
14+
Username string `yaml:"username"`
15+
Password string `yaml:"password"`
16+
}
17+
18+
// MemcachierClient is the Cache using Memcachier
19+
type MemcachierClient struct {
20+
Client *memcache.Client
21+
Expiration int32
22+
}
23+
24+
// NewMemcachierConfig returns configuration
25+
func NewMemcachierConfig(config *MemcachierConfig) *MemcachierConfig {
26+
var username, password, address string
27+
var expiration int32
28+
if config != nil {
29+
return config
30+
} else if os.Getenv("MEMCACHIER_ADDRESS") != "" {
31+
username = os.Getenv("MEMCACHIER_USERNAME")
32+
password = os.Getenv("MEMCACHIER_PASSWORD")
33+
address = os.Getenv("MEMCACHIER_ADDRESS")
34+
exp, err := strconv.Atoi(os.Getenv("MEMCACHIER_EXPIRATION"))
35+
if err != nil {
36+
return nil
37+
}
38+
expiration = int32(exp)
39+
return &MemcachierConfig{
40+
Address: address,
41+
Expiration: expiration,
42+
Username: username,
43+
Password: password,
44+
}
45+
} else {
46+
return nil
47+
}
48+
}
49+
50+
// NewMemcachierCache builds a Memcachier cache
51+
func NewMemcachierCache(config *MemcachierConfig) Cache {
52+
client := memcache.New(config.Address)
53+
client.SetAuth(config.Username, []byte(config.Password))
54+
cache := MemcachierClient{
55+
Client: client,
56+
Expiration: config.Expiration,
57+
}
58+
return &cache
59+
}
60+
61+
// Get returns NVD response for given dependency
62+
func (mc *MemcachierClient) Get(d *Dependency) []byte {
63+
item, err := mc.Client.Get(d.Key())
64+
if err != nil {
65+
return nil
66+
}
67+
return item.Value
68+
}
69+
70+
// Set put NVD response for given dependency in cache
71+
func (mc *MemcachierClient) Set(d *Dependency, v []byte) {
72+
item := memcache.Item{
73+
Key: d.Key(),
74+
Value: v,
75+
Expiration: mc.Expiration,
76+
}
77+
mc.Client.Set(&item) // nolint:errcheck // we ignore error
78+
}
79+
80+
// Ping calls Memcachier
81+
func (mc *MemcachierClient) Ping() error {
82+
item := memcache.Item{
83+
Key: "test",
84+
Value: []byte("test"),
85+
Expiration: mc.Expiration,
86+
}
87+
return mc.Client.Set(&item)
88+
}

gobinsec/cache.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ type Cache interface {
99
}
1010

1111
func BuildCache() error {
12-
if config.Memcached == nil {
13-
cache = NewMemoryCache()
12+
if conf := NewMemcachierConfig(config.Memcachier); conf != nil {
13+
cache = NewMemcachierCache(conf)
14+
} else if conf := NewMemcachedConfig(config.Memcached); conf != nil {
15+
cache = NewMemcachedCache(conf)
1416
} else {
15-
cache = NewMemcachedCache()
17+
cache = NewMemoryCache()
1618
}
1719
return cache.Ping()
1820
}

gobinsec/config.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,11 @@ import (
88
)
99

1010
type Config struct {
11-
APIKey string `yaml:"api-key"`
12-
Memcached *MemcachedConfig `yaml:"memcached"`
13-
Ignore []string `yaml:"ignore"`
14-
Strict bool `yaml:"strict"`
15-
}
16-
17-
type MemcachedConfig struct {
18-
Address string `yaml:"address"`
19-
Expiration int32 `yaml:"expiration"`
11+
APIKey string `yaml:"api-key"`
12+
Memcached *MemcachedConfig `yaml:"memcached"`
13+
Memcachier *MemcachierConfig `yaml:"memcachier"`
14+
Ignore []string `yaml:"ignore"`
15+
Strict bool `yaml:"strict"`
2016
}
2117

2218
var config Config

test/config-memcached.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,5 @@ api-key: "${NVD_API_KEY}"
22
memcached:
33
address: 127.0.0.1:11211
44
expiration: 86400
5-
username:
6-
password:
75
ignore:
86
- "CVE-2020-14040"

test/config-memcachier.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
api-key: "${NVD_API_KEY}"
2+
memcachier:
3+
address: mcx.cy.eu-central-1.ec2.memcachier.com:11211
4+
expiration: 86400
5+
username: foo
6+
password: bar
7+
ignore:
8+
- "CVE-2020-14040"

0 commit comments

Comments
 (0)