forked from projectatomic/docker-novolume-plugin
/
plugin.go
78 lines (69 loc) · 1.88 KB
/
plugin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main
import (
"bytes"
"encoding/json"
"regexp"
dockerapi "github.com/docker/docker/api"
dockerclient "github.com/docker/engine-api/client"
"github.com/docker/go-plugins-helpers/authz"
)
func newPlugin(dockerHost string) (*novolume, error) {
client, err := dockerclient.NewClient(dockerHost, dockerapi.DefaultVersion.String(), nil, nil)
if err != nil {
return nil, err
}
return &novolume{client: client}, nil
}
var (
startRegExp = regexp.MustCompile(`/containers/(.*)/start$`)
)
type novolume struct {
client *dockerclient.Client
}
func (p *novolume) AuthZReq(req authz.Request) authz.Response {
if req.RequestMethod == "POST" && startRegExp.MatchString(req.RequestURI) {
// this is deprecated in docker, remove once hostConfig is dropped to
// being available at start time
if req.RequestBody != nil {
type vfrom struct {
VolumesFrom []string
}
vf := &vfrom{}
if err := json.NewDecoder(bytes.NewReader(req.RequestBody)).Decode(vf); err != nil {
return authz.Response{Err: err.Error()}
}
if len(vf.VolumesFrom) > 0 {
goto noallow
}
}
res := startRegExp.FindStringSubmatch(req.RequestURI)
if len(res) < 1 {
return authz.Response{Err: "unable to find container name"}
}
container, err := p.client.ContainerInspect(res[1])
if err != nil {
return authz.Response{Err: err.Error()}
}
image, _, err := p.client.ImageInspectWithRaw(container.Image, false)
if err != nil {
return authz.Response{Err: err.Error()}
}
if len(image.Config.Volumes) > 0 {
goto noallow
}
for _, m := range container.Mounts {
if m.Driver != "" {
goto noallow
}
}
if len(container.HostConfig.VolumesFrom) > 0 {
goto noallow
}
}
return authz.Response{Allow: true}
noallow:
return authz.Response{Msg: "volumes are not allowed"}
}
func (p *novolume) AuthZRes(req authz.Request) authz.Response {
return authz.Response{Allow: true}
}