/
config_request.go
179 lines (152 loc) · 5.62 KB
/
config_request.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package cs_nginx
import (
"crypto/md5"
"encoding/base64"
fmt "fmt"
"io/ioutil"
"net/url"
"github.com/sirupsen/logrus"
"github.com/pkg/errors"
ac "github.com/chef/automate/api/config/shared"
w "github.com/chef/automate/api/config/shared/wrappers"
)
// NewConfigRequest returns a new instance of ConfigRequest with zero values.
func NewConfigRequest() *ConfigRequest {
return &ConfigRequest{
V1: &ConfigRequest_V1{
Sys: &ConfigRequest_V1_System{
Mlsa: &ac.Mlsa{},
Service: &ConfigRequest_V1_System_Service{},
Log: &ConfigRequest_V1_System_Log{},
Ngx: &ConfigRequest_V1_System_Nginx{
Main: &ConfigRequest_V1_System_Nginx_Main{},
Events: &ConfigRequest_V1_System_Nginx_Events{},
Http: &ConfigRequest_V1_System_Nginx_Http{},
},
RequiredRecipe: &ConfigRequest_V1_System_RequiredRecipe{},
},
Svc: &ConfigRequest_V1_Service{},
},
}
}
// DefaultConfigRequest returns a new instance of ConfigRequest with default values.
func DefaultConfigRequest() *ConfigRequest {
c := NewConfigRequest()
c.V1.Sys.Service.Port = w.Int32(10200)
c.V1.Sys.Service.Host = w.String("127.0.0.1")
c.V1.Sys.Service.StatusPort = w.Int32(10204)
c.V1.Sys.Log.Level = w.String("error")
c.V1.Sys.Ngx.Main.WorkerProcesses = w.Int32(4)
c.V1.Sys.Ngx.Events.WorkerConnections = w.Int32(10240)
c.V1.Sys.Ngx.Http.ServerNamesHashBucketSize = w.Int32(128)
c.V1.Sys.Ngx.Http.ClientMaxBodySize = w.String("250m")
c.V1.Sys.Ngx.Http.ClientBodyBufferSize = w.String("128k")
c.V1.Sys.Ngx.Http.ProxyConnectTimeout = w.Int32(1)
c.V1.Sys.Ngx.Http.KeepaliveTimeout = w.Int32(64)
c.V1.Sys.Ngx.Http.Gzip = w.String("on")
c.V1.Sys.Ngx.Http.GzipHttpVersion = w.String("1.0")
c.V1.Sys.Ngx.Http.GzipCompLevel = w.String("2")
c.V1.Sys.Ngx.Http.GzipProxied = w.String("any")
c.V1.Sys.Ngx.Http.GzipTypes = w.String("text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json") //nolint: lll
c.V1.Sys.Ngx.Http.Sendfile = w.String("on")
c.V1.Sys.Ngx.Http.TcpNodelay = w.String("on")
c.V1.Sys.Ngx.Http.TcpNopush = w.String("on")
c.V1.Sys.Ngx.Http.SslProtocols = w.String("TLSv1.2")
c.V1.Sys.Ngx.Http.SslCiphers = w.String(ac.InternalCipherSuite)
c.V1.Sys.Ngx.Http.SslVerifyDepth = w.Int32(2)
c.V1.Sys.RequiredRecipe.Enabled = w.Bool(false)
return c
}
// Validate validates that the config is sufficient to start the Service. If
// validation succeeds it will return nil, if it fails it will return a new
// instance of config.InvalidConfigError that has the missing keys and invalid
// fields populated.
func (c *ConfigRequest) Validate() error {
cfgErr := ac.NewInvalidConfigError()
rrEnabled := c.GetV1().GetSys().GetRequiredRecipe().GetEnabled().GetValue()
if rrEnabled {
// NOTE(ssd) 2018-08-02: We don't check if the file
// actually exists here only if it has been
// set. Practically, we could check for existence, but
// technically, this function runs both client-side
// and server-side.
if c.GetV1().GetSys().GetRequiredRecipe().GetPath().GetValue() == "" {
cfgErr.AddMissingKey("cs_nginx.v1.sys.required_recipe.path")
}
}
logLevel := c.GetV1().GetSys().GetLog().GetLevel().GetValue()
if logLevel != "" {
err := ac.ValidateNginxLogLevel(logLevel)
if err != nil {
cfgErr.AddInvalidValue("cs_nginx.v1.sys.log.level", err.Error())
}
}
if cfgErr.IsEmpty() {
return nil
}
return cfgErr
}
// SetGlobalConfig is a callback that allows us to populate the configuration
// of an individual service with global automate config.
func (c *ConfigRequest) SetGlobalConfig(g *ac.GlobalConfig) {
c.V1.Sys.Mlsa = g.V1.Mlsa
if logLevel := g.GetV1().GetLog().GetLevel().GetValue(); logLevel != "" {
c.V1.Sys.Log.Level.Value = ac.GlobalLogLevelToNginxLevel(logLevel)
}
if gExternalAutomate := g.GetV1().GetExternal().GetAutomate(); gExternalAutomate.GetEnable().GetValue() {
externalAutomateURL, err := url.Parse(gExternalAutomate.GetNode().GetValue())
if err != nil {
logrus.WithError(err).Error("failed to parse external automate url")
return
}
host := externalAutomateURL.Host
port := externalAutomateURL.Port()
scheme := externalAutomateURL.Scheme
if scheme == "" {
scheme = "https"
}
if port == "" {
switch scheme {
case "https":
port = "443"
case "http":
port = "80"
}
}
endpoint := fmt.Sprintf("%s:%s", host, port)
c.V1.Sys.ExternalAutomate = &ConfigRequest_V1_System_ExternalAutomate{
Enable: w.Bool(true),
SslUpstream: w.Bool(scheme == "https"),
Endpoint: w.String(endpoint),
RootCert: gExternalAutomate.GetSsl().GetRootCert(),
ServerName: gExternalAutomate.GetSsl().GetServerName(),
Token: gExternalAutomate.GetAuth().GetToken(),
}
}
}
// PrepareSystemConfig returns a system configuration that can be used
// to start the service.
func (c *ConfigRequest) PrepareSystemConfig(creds *ac.TLSCredentials) (ac.PreparedSystemConfig, error) {
c.V1.Sys.Tls = creds
if c.V1.Sys.GetRequiredRecipe().GetEnabled().GetValue() {
rrPath := c.V1.Sys.RequiredRecipe.Path.GetValue()
rrContent, err := ioutil.ReadFile(rrPath)
if err != nil {
return nil, errors.Wrapf(err, "could not read required recipe at %q", rrPath)
}
c.V1.Sys.RequiredRecipe.ContentMd5 = w.String(CalculateContentMD5(rrContent))
}
return c.V1.Sys, nil
}
// CalculateContentMD5 returns a base-64 encoded MD5 sum of the given
// bytes.
//
// To ensure compatibility with the upstream chef-server this should
// be the same as the value returned by Ruby's
//
// Digest::MD5.base64digest
//
func CalculateContentMD5(data []byte) string {
md5sum := md5.Sum(data) // nosemgrep
return base64.StdEncoding.EncodeToString(md5sum[:])
}