kuma
261 строка · 9.4 Кб
1package api_server
2
3import (
4"net/url"
5
6"github.com/pkg/errors"
7"go.uber.org/multierr"
8
9"github.com/kumahq/kuma/pkg/config"
10config_types "github.com/kumahq/kuma/pkg/config/types"
11)
12
13var _ config.Config = &ApiServerConfig{}
14
15// ApiServerConfig defines API Server configuration
16type ApiServerConfig struct {
17config.BaseConfig
18
19// If true, then API Server will operate in read only mode (serving GET requests)
20ReadOnly bool `json:"readOnly" envconfig:"kuma_api_server_read_only"`
21// Allowed domains for Cross-Origin Resource Sharing. The value can be either domain or regexp
22CorsAllowedDomains []string `json:"corsAllowedDomains" envconfig:"kuma_api_server_cors_allowed_domains"`
23// HTTP configuration of the API Server
24HTTP ApiServerHTTPConfig `json:"http"`
25// HTTPS configuration of the API Server
26HTTPS ApiServerHTTPSConfig `json:"https"`
27// Authentication configuration for administrative endpoints like Dataplane Token or managing Secrets
28Auth ApiServerAuth `json:"auth"`
29// Authentication configuration for API Server
30Authn ApiServerAuthn `json:"authn"`
31// BasePath the path to serve the API from
32BasePath string `json:"basePath" envconfig:"kuma_api_server_base_path"`
33// RootUrl can be used if you use a reverse proxy
34RootUrl string `json:"rootUrl" envconfig:"kuma_api_server_root_url"`
35// GUI configuration specific to the GUI
36GUI ApiServerGUI `json:"gui,omitempty"`
37}
38
39type ApiServerGUI struct {
40// Enabled whether to serve to gui (if mode=zone this has no effect)
41Enabled bool `json:"enabled" envconfig:"kuma_api_server_gui_enabled"`
42// RootUrl can be used if you set a reverse proxy or want to serve the gui from a different path
43RootUrl string `json:"rootUrl" envconfig:"kuma_api_server_gui_root_url"`
44// BasePath the path to serve the GUI from
45BasePath string `json:"basePath" envconfig:"kuma_api_server_gui_base_path"`
46}
47
48func (a *ApiServerGUI) Validate() error {
49var errs error
50if a.RootUrl != "" {
51_, err := url.Parse(a.RootUrl)
52if err != nil {
53errs = multierr.Append(errs, errors.New("RootUrl is not a valid url"))
54}
55}
56if a.BasePath != "" {
57_, err := url.Parse(a.BasePath)
58if err != nil {
59errs = multierr.Append(errs, errors.New("BaseGuiPath is not a valid url"))
60}
61}
62return errs
63}
64
65// ApiServerHTTPConfig defines API Server HTTP configuration
66type ApiServerHTTPConfig struct {
67// If true then API Server will be served on HTTP
68Enabled bool `json:"enabled" envconfig:"kuma_api_server_http_enabled"`
69// Network interface on which HTTP API Server will be exposed
70Interface string `json:"interface" envconfig:"kuma_api_server_http_interface"`
71// Port of the HTTP API Server
72Port uint32 `json:"port" envconfig:"kuma_api_server_http_port"`
73}
74
75func (a *ApiServerHTTPConfig) Validate() error {
76var errs error
77if a.Interface == "" {
78errs = multierr.Append(errs, errors.New("Interface cannot be empty"))
79}
80if a.Port > 65535 {
81errs = multierr.Append(errs, errors.New("Port must be in range [0, 65535]"))
82}
83return errs
84}
85
86// ApiServerHTTPSConfig defines API Server HTTPS configuration
87type ApiServerHTTPSConfig struct {
88// If true then API Server will be served on HTTPS
89Enabled bool `json:"enabled" envconfig:"kuma_api_server_https_enabled"`
90// Network interface on which HTTPS API Server will be exposed
91Interface string `json:"interface" envconfig:"kuma_api_server_https_interface"`
92// Port of the HTTPS API Server
93Port uint32 `json:"port" envconfig:"kuma_api_server_https_port"`
94// Path to TLS certificate file. Autoconfigured from KUMA_GENERAL_TLS_CERT_FILE if empty
95TlsCertFile string `json:"tlsCertFile" envconfig:"kuma_api_server_https_tls_cert_file"`
96// Path to TLS key file. Autoconfigured from KUMA_GENERAL_TLS_KEY_FILE if empty
97TlsKeyFile string `json:"tlsKeyFile" envconfig:"kuma_api_server_https_tls_key_file"`
98// TlsMinVersion defines the minimum TLS version to be used
99TlsMinVersion string `json:"tlsMinVersion" envconfig:"kuma_api_server_https_tls_min_version"`
100// TlsMaxVersion defines the maximum TLS version to be used
101TlsMaxVersion string `json:"tlsMaxVersion" envconfig:"kuma_api_server_https_tls_max_version"`
102// TlsCipherSuites defines the list of ciphers to use
103TlsCipherSuites []string `json:"tlsCipherSuites" envconfig:"kuma_api_server_https_tls_cipher_suites"`
104// If true, then HTTPS connection will require client cert.
105RequireClientCert bool `json:"requireClientCert" envconfig:"kuma_api_server_https_require_client_cert"`
106// Path to the CA certificate which is used to sign client certificates. It is used only for verifying client certificates.
107TlsCaFile string `json:"tlsCaFile" envconfig:"kuma_api_server_https_tls_ca_file"`
108}
109
110func (a *ApiServerHTTPSConfig) Validate() error {
111var errs error
112if a.Interface == "" {
113errs = multierr.Append(errs, errors.New(".Interface cannot be empty"))
114}
115if a.Port > 65535 {
116return errors.New("Port must be in range [0, 65535]")
117}
118if (a.TlsKeyFile == "" && a.TlsCertFile != "") || (a.TlsKeyFile != "" && a.TlsCertFile == "") {
119errs = multierr.Append(errs, errors.New("Both TlsCertFile and TlsKeyFile has to be specified"))
120}
121if _, err := config_types.TLSVersion(a.TlsMinVersion); err != nil {
122errs = multierr.Append(errs, errors.New(".TlsMinVersion"+err.Error()))
123}
124if _, err := config_types.TLSVersion(a.TlsMaxVersion); err != nil {
125errs = multierr.Append(errs, errors.New(".TlsMaxVersion"+err.Error()))
126}
127if _, err := config_types.TLSCiphers(a.TlsCipherSuites); err != nil {
128errs = multierr.Append(errs, errors.New(".TlsCipherSuites"+err.Error()))
129}
130return errs
131}
132
133// ApiServerAuth defines API Server authentication configuration
134type ApiServerAuth struct {
135// Directory of authorized client certificates (only valid in HTTPS)
136ClientCertsDir string `json:"clientCertsDir" envconfig:"kuma_api_server_auth_client_certs_dir"`
137}
138
139// ApiServerAuthn defines Api Server Authentication configuration
140type ApiServerAuthn struct {
141// Type of authentication mechanism (available values: "clientCerts", "tokens")
142Type string `json:"type" envconfig:"kuma_api_server_authn_type"`
143// Localhost is authenticated as a user admin of group admin
144LocalhostIsAdmin bool `json:"localhostIsAdmin" envconfig:"kuma_api_server_authn_localhost_is_admin"`
145// Configuration for tokens authentication
146Tokens ApiServerAuthnTokens `json:"tokens"`
147}
148
149func (a ApiServerAuthn) Validate() error {
150if a.Type == "tokens" {
151if err := a.Tokens.Validate(); err != nil {
152return errors.Wrap(err, ".Tokens is not valid")
153}
154}
155return nil
156}
157
158type ApiServerAuthnTokens struct {
159// If true then User Token with name admin and group admin will be created and placed as admin-user-token Kuma Global Secret
160BootstrapAdminToken bool `json:"bootstrapAdminToken" envconfig:"kuma_api_server_authn_tokens_bootstrap_admin_token"`
161// If true the control plane token issuer is enabled. It's recommended to set it to false when all the tokens are issued offline.
162EnableIssuer bool `json:"enableIssuer" envconfig:"kuma_api_server_authn_tokens_enable_issuer"`
163// Token validator configuration
164Validator TokensValidator `json:"validator"`
165}
166
167func (a ApiServerAuthnTokens) Validate() error {
168if err := a.Validator.Validate(); err != nil {
169return errors.Wrap(err, ".Validator is not valid")
170}
171return nil
172}
173
174var _ config.Config = TokensValidator{}
175
176type TokensValidator struct {
177config.BaseConfig
178
179// If true then Kuma secrets with prefix "user-token-signing-key" are considered as signing keys.
180UseSecrets bool `json:"useSecrets" envconfig:"kuma_api_server_authn_tokens_validator_use_secrets"`
181// List of public keys used to validate the token.
182PublicKeys []config_types.PublicKey `json:"publicKeys"`
183}
184
185func (t TokensValidator) Validate() error {
186for i, key := range t.PublicKeys {
187if err := key.Validate(); err != nil {
188return errors.Wrapf(err, ".PublicKeys[%d] is not valid", i)
189}
190}
191return nil
192}
193
194func (a *ApiServerConfig) Validate() error {
195var errs error
196if err := a.HTTP.Validate(); err != nil {
197errs = multierr.Append(err, errors.Wrap(err, ".HTTP not valid"))
198}
199if err := a.HTTPS.Validate(); err != nil {
200errs = multierr.Append(err, errors.Wrap(err, ".HTTPS not valid"))
201}
202if err := a.GUI.Validate(); err != nil {
203errs = multierr.Append(err, errors.Wrap(err, ".GUI not valid"))
204}
205if a.RootUrl != "" {
206if _, err := url.Parse(a.RootUrl); err != nil {
207errs = multierr.Append(err, errors.New("RootUrl is not a valid URL"))
208}
209}
210if a.BasePath != "" {
211_, err := url.Parse(a.BasePath)
212if err != nil {
213errs = multierr.Append(errs, errors.New("BaseGuiPath is not a valid url"))
214}
215}
216if err := a.Authn.Validate(); err != nil {
217errs = multierr.Append(err, errors.Wrap(err, ".Authn is not valid"))
218}
219return errs
220}
221
222func DefaultApiServerConfig() *ApiServerConfig {
223return &ApiServerConfig{
224ReadOnly: false,
225CorsAllowedDomains: []string{".*"},
226BasePath: "/",
227HTTP: ApiServerHTTPConfig{
228Enabled: true,
229Interface: "0.0.0.0",
230Port: 5681,
231},
232HTTPS: ApiServerHTTPSConfig{
233Enabled: true,
234Interface: "0.0.0.0",
235Port: 5682,
236TlsCertFile: "", // autoconfigured
237TlsKeyFile: "", // autoconfigured
238TlsMinVersion: "TLSv1_2",
239TlsCipherSuites: []string{},
240},
241Auth: ApiServerAuth{
242ClientCertsDir: "",
243},
244Authn: ApiServerAuthn{
245Type: "tokens",
246LocalhostIsAdmin: true,
247Tokens: ApiServerAuthnTokens{
248BootstrapAdminToken: true,
249EnableIssuer: true,
250Validator: TokensValidator{
251UseSecrets: true,
252PublicKeys: []config_types.PublicKey{},
253},
254},
255},
256GUI: ApiServerGUI{
257Enabled: true,
258BasePath: "/gui",
259},
260}
261}
262