agent: add "http_config"

This patch adds an "http_config" object to the config file
and moves the "http_api_response_headers" option there.

"http_api_response_headers" is now deprecated in favor of
"http_config.response_headers"
This commit is contained in:
wojtkiewicz 2017-06-16 13:58:19 +02:00 committed by Frank Schroeder
parent c7f35ef2f9
commit 37785028be
No known key found for this signature in database
GPG Key ID: 4D65C6EAEC87DECD
5 changed files with 70 additions and 20 deletions

View File

@ -129,6 +129,12 @@ type DNSConfig struct {
RecursorTimeoutRaw string `mapstructure:"recursor_timeout" json:"-"` RecursorTimeoutRaw string `mapstructure:"recursor_timeout" json:"-"`
} }
// HTTPConfig is used to fine tune the Http sub-system.
type HTTPConfig struct {
// ResponseHeaders are used to add HTTP header response fields to the HTTP API responses.
ResponseHeaders map[string]string `mapstructure:"response_headers"`
}
// RetryJoinEC2 is used to configure discovery of instances via Amazon's EC2 api // RetryJoinEC2 is used to configure discovery of instances via Amazon's EC2 api
type RetryJoinEC2 struct { type RetryJoinEC2 struct {
// The AWS region to look for instances in // The AWS region to look for instances in
@ -365,6 +371,9 @@ type Config struct {
// Domain is the DNS domain for the records. Defaults to "consul." // Domain is the DNS domain for the records. Defaults to "consul."
Domain string `mapstructure:"domain"` Domain string `mapstructure:"domain"`
// HTTP configuration
HTTPConfig HTTPConfig `mapstructure:"http_config"`
// Encryption key to use for the Serf communication // Encryption key to use for the Serf communication
EncryptKey string `mapstructure:"encrypt" json:"-"` EncryptKey string `mapstructure:"encrypt" json:"-"`
@ -706,9 +715,6 @@ type Config struct {
// send with the update check. This is used to deduplicate messages. // send with the update check. This is used to deduplicate messages.
DisableAnonymousSignature bool `mapstructure:"disable_anonymous_signature"` DisableAnonymousSignature bool `mapstructure:"disable_anonymous_signature"`
// HTTPAPIResponseHeaders are used to add HTTP header response fields to the HTTP API responses.
HTTPAPIResponseHeaders map[string]string `mapstructure:"http_api_response_headers"`
// AEInterval controls the anti-entropy interval. This is how often // AEInterval controls the anti-entropy interval. This is how often
// the agent attempts to reconcile its local state with the server's // the agent attempts to reconcile its local state with the server's
// representation of our state. Defaults to every 60s. // representation of our state. Defaults to every 60s.
@ -764,6 +770,7 @@ type Config struct {
DeprecatedAtlasACLToken string `mapstructure:"atlas_acl_token" json:"-"` DeprecatedAtlasACLToken string `mapstructure:"atlas_acl_token" json:"-"`
DeprecatedAtlasJoin bool `mapstructure:"atlas_join" json:"-"` DeprecatedAtlasJoin bool `mapstructure:"atlas_join" json:"-"`
DeprecatedAtlasEndpoint string `mapstructure:"atlas_endpoint" json:"-"` DeprecatedAtlasEndpoint string `mapstructure:"atlas_endpoint" json:"-"`
DeprecatedHTTPAPIResponseHeaders map[string]string `mapstructure:"http_api_response_headers"`
} }
// IncomingHTTPSConfig returns the TLS configuration for HTTPS // IncomingHTTPSConfig returns the TLS configuration for HTTPS
@ -1368,6 +1375,19 @@ func DecodeConfig(r io.Reader) (*Config, error) {
result.TLSCipherSuites = ciphers result.TLSCipherSuites = ciphers
} }
// This is for backwards compatibility.
// HTTPAPIResponseHeaders has been replaced with HTTPConfig.ResponseHeaders
if len(result.DeprecatedHTTPAPIResponseHeaders) > 0 {
fmt.Fprintln(os.Stderr, "==> DEPRECATION: http_api_response_headers is deprecated and "+
"is no longer used. Please use http_config.response_headers instead.")
if result.HTTPConfig.ResponseHeaders == nil {
result.HTTPConfig.ResponseHeaders = make(map[string]string)
}
for field, value := range result.DeprecatedHTTPAPIResponseHeaders {
result.HTTPConfig.ResponseHeaders[field] = value
}
result.DeprecatedHTTPAPIResponseHeaders = nil
}
return &result, nil return &result, nil
} }
@ -1974,12 +1994,12 @@ func MergeConfig(a, b *Config) *Config {
result.SessionTTLMin = b.SessionTTLMin result.SessionTTLMin = b.SessionTTLMin
result.SessionTTLMinRaw = b.SessionTTLMinRaw result.SessionTTLMinRaw = b.SessionTTLMinRaw
} }
if len(b.HTTPAPIResponseHeaders) != 0 { if len(b.HTTPConfig.ResponseHeaders) > 0 {
if result.HTTPAPIResponseHeaders == nil { if result.HTTPConfig.ResponseHeaders == nil {
result.HTTPAPIResponseHeaders = make(map[string]string) result.HTTPConfig.ResponseHeaders = make(map[string]string)
} }
for field, value := range b.HTTPAPIResponseHeaders { for field, value := range b.HTTPConfig.ResponseHeaders {
result.HTTPAPIResponseHeaders[field] = value result.HTTPConfig.ResponseHeaders[field] = value
} }
} }
if len(b.Meta) != 0 { if len(b.Meta) != 0 {

View File

@ -332,7 +332,11 @@ func TestDecodeConfig(t *testing.T) {
}, },
{ {
in: `{"http_api_response_headers":{"a":"b","c":"d"}}`, in: `{"http_api_response_headers":{"a":"b","c":"d"}}`,
c: &Config{HTTPAPIResponseHeaders: map[string]string{"a": "b", "c": "d"}}, c: &Config{HTTPConfig: HTTPConfig{ResponseHeaders: map[string]string{"a": "b", "c": "d"}}},
},
{
in: `{"http_config":{"response_headers":{"a":"b","c":"d"}}}`,
c: &Config{HTTPConfig: HTTPConfig{ResponseHeaders: map[string]string{"a": "b", "c": "d"}}},
}, },
{ {
in: `{"key_file":"a"}`, in: `{"key_file":"a"}`,
@ -1389,9 +1393,11 @@ func TestMergeConfig(t *testing.T) {
}, },
DisableUpdateCheck: true, DisableUpdateCheck: true,
DisableAnonymousSignature: true, DisableAnonymousSignature: true,
HTTPAPIResponseHeaders: map[string]string{ HTTPConfig: HTTPConfig{
ResponseHeaders: map[string]string{
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
}, },
},
UnixSockets: UnixSocketConfig{ UnixSockets: UnixSocketConfig{
UnixSocketPermissions{ UnixSocketPermissions{
Usr: "500", Usr: "500",

View File

@ -162,7 +162,7 @@ func (s *HTTPServer) handler(enableDebug bool) http.Handler {
// wrap is used to wrap functions to make them more convenient // wrap is used to wrap functions to make them more convenient
func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Request) (interface{}, error)) http.HandlerFunc { func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Request) (interface{}, error)) http.HandlerFunc {
return func(resp http.ResponseWriter, req *http.Request) { return func(resp http.ResponseWriter, req *http.Request) {
setHeaders(resp, s.agent.config.HTTPAPIResponseHeaders) setHeaders(resp, s.agent.config.HTTPConfig.ResponseHeaders)
setTranslateAddr(resp, s.agent.config.TranslateWanAddrs) setTranslateAddr(resp, s.agent.config.TranslateWanAddrs)
// Obfuscate any tokens from appearing in the logs // Obfuscate any tokens from appearing in the logs

View File

@ -241,7 +241,7 @@ func TestHTTPAPI_TranslateAddrHeader(t *testing.T) {
func TestHTTPAPIResponseHeaders(t *testing.T) { func TestHTTPAPIResponseHeaders(t *testing.T) {
t.Parallel() t.Parallel()
cfg := TestConfig() cfg := TestConfig()
cfg.HTTPAPIResponseHeaders = map[string]string{ cfg.HTTPConfig.ResponseHeaders = map[string]string{
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
"X-XSS-Protection": "1; mode=block", "X-XSS-Protection": "1; mode=block",
} }

View File

@ -745,6 +745,30 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
} }
``` ```
This has been deprecated in Consul 0.9.0. Setting this value will set `http_config.response_headers`
instead for backwards compatibility.
* <a name="http_config"></a><a href="#http_config">`http_config`</a>
This object allows setting options for the HTTP API.
<br><br>
The following sub-keys are available:
* <a name="response_headers"></a><a href="#response_headers">`response_headers`</a>
This object allows adding headers to the HTTP API responses.
For example, the following config can be used to enable
[CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) on
the HTTP API endpoints:
```javascript
{
"http_config": {
"response_headers": {
"Access-Control-Allow-Origin": "*"
}
}
}
```
* <a name="leave_on_terminate"></a><a href="#leave_on_terminate">`leave_on_terminate`</a> If * <a name="leave_on_terminate"></a><a href="#leave_on_terminate">`leave_on_terminate`</a> If
enabled, when the agent receives a TERM signal, it will send a `Leave` message to the rest enabled, when the agent receives a TERM signal, it will send a `Leave` message to the rest
of the cluster and gracefully leave. The default behavior for this feature varies based on of the cluster and gracefully leave. The default behavior for this feature varies based on