Issues (121)

report/saas.go (4 issues)

Severity
1
/* Vuls - Vulnerability Scanner
2
Copyright (C) 2016  Future Corporation , Japan.
3
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation, either version 3 of the License, or
7
(at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
package report
19
20
import (
21
	"bytes"
22
	"encoding/json"
23
	"fmt"
24
	"io/ioutil"
25
	"net/http"
26
	"net/url"
27
	"os"
28
	"path"
29
	"strings"
30
	"time"
31
32
	"github.com/aws/aws-sdk-go/aws"
33
	"github.com/aws/aws-sdk-go/aws/credentials"
34
	"github.com/aws/aws-sdk-go/aws/session"
35
	"github.com/aws/aws-sdk-go/service/s3"
36
	"github.com/aws/aws-sdk-go/service/sts"
37
	c "github.com/future-architect/vuls/config"
38
	"github.com/future-architect/vuls/models"
39
	"github.com/future-architect/vuls/util"
40
	"golang.org/x/xerrors"
41
)
42
43
// SaasWriter writes results to SaaS
44
type SaasWriter struct{}
45
46
// TempCredential : TempCredential
47
type TempCredential struct {
48
	Credential   *sts.Credentials `json:"Credential"`
49
	S3Bucket     string           `json:"S3Bucket"`
50
	S3ResultsDir string           `json:"S3ResultsDir"`
51
}
52
53
type payload struct {
54
	GroupID      int    `json:"GroupID"`
55
	Token        string `json:"Token"`
56
	ScannedBy    string `json:"ScannedBy"`
57
	ScannedIPv4s string `json:"ScannedIPv4s"`
58
	ScannedIPv6s string `json:"ScannedIPv6s"`
59
}
60
61
// UploadSaas : UploadSaas
62
func (w SaasWriter) Write(rs ...models.ScanResult) (err error) {
63
	// dir string, configPath string, config *c.Config
64
	if len(rs) == 0 {
65
		return nil
66
	}
67
68
	ipv4s, ipv6s, err := util.IP()
69
	if err != nil {
70
		util.Log.Errorf("Failed to fetch scannedIPs. err: %+v", err)
71
	}
72
	hostname, _ := os.Hostname()
73
74
	payload := payload{
75
		GroupID:      c.Conf.Saas.GroupID,
76
		Token:        c.Conf.Saas.Token,
77
		ScannedBy:    hostname,
78
		ScannedIPv4s: strings.Join(ipv4s, ", "),
79
		ScannedIPv6s: strings.Join(ipv6s, ", "),
80
	}
81
82
	var body []byte
83
	if body, err = json.Marshal(payload); err != nil {
84
		return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
85
	}
86
87
	var req *http.Request
88
	if req, err = http.NewRequest("POST", c.Conf.Saas.URL, bytes.NewBuffer(body)); err != nil {
89
		return err
90
	}
91
	req.Header.Set("Content-Type", "application/json")
92
	req.Header.Set("Accept", "application/json")
93
94
	proxy := c.Conf.HTTPProxy
95
	var client http.Client
96
	if proxy != "" {
97
		proxyURL, _ := url.Parse(proxy)
98
		client = http.Client{
99
			Transport: &http.Transport{
100
				Proxy: http.ProxyURL(proxyURL),
101
			},
102
		}
103
	} else {
104
		client = http.Client{}
105
	}
106
107
	var resp *http.Response
108
	if resp, err = client.Do(req); err != nil {
109
		return err
110
	}
111
	defer resp.Body.Close()
112
	if resp.StatusCode != 200 {
113
		return xerrors.Errorf("Failed to get Credential. Request JSON : %s,", string(body))
114
	}
115
116
	var t []byte
117
	if t, err = ioutil.ReadAll(resp.Body); err != nil {
118
		return err
119
	}
120
121
	var tempCredential TempCredential
122
	if err = json.Unmarshal(t, &tempCredential); err != nil {
123
		return xerrors.Errorf("Failed to unmarshal saas credential file. err : %s", err)
124
	}
125
126
	credential := credentials.NewStaticCredentialsFromCreds(credentials.Value{
127
		AccessKeyID:     *tempCredential.Credential.AccessKeyId,
128
		SecretAccessKey: *tempCredential.Credential.SecretAccessKey,
129
		SessionToken:    *tempCredential.Credential.SessionToken,
130
	})
131
132
	var sess *session.Session
133
	if sess, err = session.NewSession(&aws.Config{
134
		Credentials: credential,
135
		Region:      aws.String("ap-northeast-1"),
136
	}); err != nil {
137
		return xerrors.Errorf("Failed to new aws session. err: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
138
	}
139
140
	svc := s3.New(sess)
141
	for _, r := range rs {
142
		s3Key := renameKeyNameUTC(r.ScannedAt, r.ServerUUID, r.Container)
143
		var b []byte
144
		if b, err = json.Marshal(r); err != nil {
145
			return xerrors.Errorf("Failed to Marshal to JSON: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
146
		}
147
		util.Log.Infof("Uploading...: ServerName: %s, ", r.ServerName)
148
		putObjectInput := &s3.PutObjectInput{
149
			Bucket: aws.String(tempCredential.S3Bucket),
150
			Key:    aws.String(path.Join(tempCredential.S3ResultsDir, s3Key)),
151
			Body:   bytes.NewReader(b),
152
		}
153
154
		if _, err := svc.PutObject(putObjectInput); err != nil {
155
			return xerrors.Errorf("Failed to upload data to %s/%s, err: %w",
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
156
				tempCredential.S3Bucket, s3Key, err)
157
		}
158
	}
159
	return nil
160
}
161
162
func renameKeyNameUTC(scannedAt time.Time, uuid string, container models.Container) string {
163
	timestr := scannedAt.UTC().Format(time.RFC3339)
164
	if len(container.ContainerID) == 0 {
165
		return fmt.Sprintf("%s/%s.json", timestr, uuid)
166
	}
167
	return fmt.Sprintf("%s/%s@%s.json", timestr, container.UUID, uuid)
168
}
169