From 8dd50d5b2d93ea23d14c98c48254242b6fa4d610 Mon Sep 17 00:00:00 2001 From: Paul Banks Date: Thu, 26 Jul 2018 13:53:39 +0100 Subject: [PATCH] Add config option to disable HTTP printable char path check (#4442) --- agent/config/builder.go | 1 + agent/config/config.go | 201 +++++++++++----------- agent/config/runtime.go | 10 ++ agent/config/runtime_test.go | 142 +++++++-------- agent/http.go | 9 +- agent/http_test.go | 13 ++ website/source/docs/agent/options.html.md | 11 ++ 7 files changed, 216 insertions(+), 171 deletions(-) diff --git a/agent/config/builder.go b/agent/config/builder.go index f850d5134982..d76196795e7b 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -693,6 +693,7 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { DisableAnonymousSignature: b.boolVal(c.DisableAnonymousSignature), DisableCoordinates: b.boolVal(c.DisableCoordinates), DisableHostNodeID: b.boolVal(c.DisableHostNodeID), + DisableHTTPUnprintableCharFilter: b.boolVal(c.DisableHTTPUnprintableCharFilter), DisableKeyringFile: b.boolVal(c.DisableKeyringFile), DisableRemoteExec: b.boolVal(c.DisableRemoteExec), DisableUpdateCheck: b.boolVal(c.DisableUpdateCheck), diff --git a/agent/config/config.go b/agent/config/config.go index 76af50b7d7dc..e49b7f9d638b 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -136,106 +136,107 @@ func Parse(data string, format string) (c Config, err error) { // configuration it should be treated as an external API which cannot be // changed and refactored at will since this will break existing setups. type Config struct { - ACLAgentMasterToken *string `json:"acl_agent_master_token,omitempty" hcl:"acl_agent_master_token" mapstructure:"acl_agent_master_token"` - ACLAgentToken *string `json:"acl_agent_token,omitempty" hcl:"acl_agent_token" mapstructure:"acl_agent_token"` - ACLDatacenter *string `json:"acl_datacenter,omitempty" hcl:"acl_datacenter" mapstructure:"acl_datacenter"` - ACLDefaultPolicy *string `json:"acl_default_policy,omitempty" hcl:"acl_default_policy" mapstructure:"acl_default_policy"` - ACLDownPolicy *string `json:"acl_down_policy,omitempty" hcl:"acl_down_policy" mapstructure:"acl_down_policy"` - ACLEnableKeyListPolicy *bool `json:"acl_enable_key_list_policy,omitempty" hcl:"acl_enable_key_list_policy" mapstructure:"acl_enable_key_list_policy"` - ACLEnforceVersion8 *bool `json:"acl_enforce_version_8,omitempty" hcl:"acl_enforce_version_8" mapstructure:"acl_enforce_version_8"` - ACLMasterToken *string `json:"acl_master_token,omitempty" hcl:"acl_master_token" mapstructure:"acl_master_token"` - ACLReplicationToken *string `json:"acl_replication_token,omitempty" hcl:"acl_replication_token" mapstructure:"acl_replication_token"` - ACLTTL *string `json:"acl_ttl,omitempty" hcl:"acl_ttl" mapstructure:"acl_ttl"` - ACLToken *string `json:"acl_token,omitempty" hcl:"acl_token" mapstructure:"acl_token"` - Addresses Addresses `json:"addresses,omitempty" hcl:"addresses" mapstructure:"addresses"` - AdvertiseAddrLAN *string `json:"advertise_addr,omitempty" hcl:"advertise_addr" mapstructure:"advertise_addr"` - AdvertiseAddrWAN *string `json:"advertise_addr_wan,omitempty" hcl:"advertise_addr_wan" mapstructure:"advertise_addr_wan"` - Autopilot Autopilot `json:"autopilot,omitempty" hcl:"autopilot" mapstructure:"autopilot"` - BindAddr *string `json:"bind_addr,omitempty" hcl:"bind_addr" mapstructure:"bind_addr"` - Bootstrap *bool `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"` - BootstrapExpect *int `json:"bootstrap_expect,omitempty" hcl:"bootstrap_expect" mapstructure:"bootstrap_expect"` - CAFile *string `json:"ca_file,omitempty" hcl:"ca_file" mapstructure:"ca_file"` - CAPath *string `json:"ca_path,omitempty" hcl:"ca_path" mapstructure:"ca_path"` - CertFile *string `json:"cert_file,omitempty" hcl:"cert_file" mapstructure:"cert_file"` - Check *CheckDefinition `json:"check,omitempty" hcl:"check" mapstructure:"check"` // needs to be a pointer to avoid partial merges - CheckUpdateInterval *string `json:"check_update_interval,omitempty" hcl:"check_update_interval" mapstructure:"check_update_interval"` - Checks []CheckDefinition `json:"checks,omitempty" hcl:"checks" mapstructure:"checks"` - ClientAddr *string `json:"client_addr,omitempty" hcl:"client_addr" mapstructure:"client_addr"` - Connect Connect `json:"connect,omitempty" hcl:"connect" mapstructure:"connect"` - DNS DNS `json:"dns_config,omitempty" hcl:"dns_config" mapstructure:"dns_config"` - DNSDomain *string `json:"domain,omitempty" hcl:"domain" mapstructure:"domain"` - DNSRecursors []string `json:"recursors,omitempty" hcl:"recursors" mapstructure:"recursors"` - DataDir *string `json:"data_dir,omitempty" hcl:"data_dir" mapstructure:"data_dir"` - Datacenter *string `json:"datacenter,omitempty" hcl:"datacenter" mapstructure:"datacenter"` - DisableAnonymousSignature *bool `json:"disable_anonymous_signature,omitempty" hcl:"disable_anonymous_signature" mapstructure:"disable_anonymous_signature"` - DisableCoordinates *bool `json:"disable_coordinates,omitempty" hcl:"disable_coordinates" mapstructure:"disable_coordinates"` - DisableHostNodeID *bool `json:"disable_host_node_id,omitempty" hcl:"disable_host_node_id" mapstructure:"disable_host_node_id"` - DisableKeyringFile *bool `json:"disable_keyring_file,omitempty" hcl:"disable_keyring_file" mapstructure:"disable_keyring_file"` - DisableRemoteExec *bool `json:"disable_remote_exec,omitempty" hcl:"disable_remote_exec" mapstructure:"disable_remote_exec"` - DisableUpdateCheck *bool `json:"disable_update_check,omitempty" hcl:"disable_update_check" mapstructure:"disable_update_check"` - DiscardCheckOutput *bool `json:"discard_check_output" hcl:"discard_check_output" mapstructure:"discard_check_output"` - DiscoveryMaxStale *string `json:"discovery_max_stale" hcl:"discovery_max_stale" mapstructure:"discovery_max_stale"` - EnableACLReplication *bool `json:"enable_acl_replication,omitempty" hcl:"enable_acl_replication" mapstructure:"enable_acl_replication"` - EnableAgentTLSForChecks *bool `json:"enable_agent_tls_for_checks,omitempty" hcl:"enable_agent_tls_for_checks" mapstructure:"enable_agent_tls_for_checks"` - EnableDebug *bool `json:"enable_debug,omitempty" hcl:"enable_debug" mapstructure:"enable_debug"` - EnableScriptChecks *bool `json:"enable_script_checks,omitempty" hcl:"enable_script_checks" mapstructure:"enable_script_checks"` - EnableSyslog *bool `json:"enable_syslog,omitempty" hcl:"enable_syslog" mapstructure:"enable_syslog"` - EncryptKey *string `json:"encrypt,omitempty" hcl:"encrypt" mapstructure:"encrypt"` - EncryptVerifyIncoming *bool `json:"encrypt_verify_incoming,omitempty" hcl:"encrypt_verify_incoming" mapstructure:"encrypt_verify_incoming"` - EncryptVerifyOutgoing *bool `json:"encrypt_verify_outgoing,omitempty" hcl:"encrypt_verify_outgoing" mapstructure:"encrypt_verify_outgoing"` - HTTPConfig HTTPConfig `json:"http_config,omitempty" hcl:"http_config" mapstructure:"http_config"` - KeyFile *string `json:"key_file,omitempty" hcl:"key_file" mapstructure:"key_file"` - LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"` - Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"` - LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"` - NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"` - NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"` - NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"` - NonVotingServer *bool `json:"non_voting_server,omitempty" hcl:"non_voting_server" mapstructure:"non_voting_server"` - Performance Performance `json:"performance,omitempty" hcl:"performance" mapstructure:"performance"` - PidFile *string `json:"pid_file,omitempty" hcl:"pid_file" mapstructure:"pid_file"` - Ports Ports `json:"ports,omitempty" hcl:"ports" mapstructure:"ports"` - RPCProtocol *int `json:"protocol,omitempty" hcl:"protocol" mapstructure:"protocol"` - RaftProtocol *int `json:"raft_protocol,omitempty" hcl:"raft_protocol" mapstructure:"raft_protocol"` - RaftSnapshotThreshold *int `json:"raft_snapshot_threshold,omitempty" hcl:"raft_snapshot_threshold" mapstructure:"raft_snapshot_threshold"` - RaftSnapshotInterval *string `json:"raft_snapshot_interval,omitempty" hcl:"raft_snapshot_interval" mapstructure:"raft_snapshot_interval"` - ReconnectTimeoutLAN *string `json:"reconnect_timeout,omitempty" hcl:"reconnect_timeout" mapstructure:"reconnect_timeout"` - ReconnectTimeoutWAN *string `json:"reconnect_timeout_wan,omitempty" hcl:"reconnect_timeout_wan" mapstructure:"reconnect_timeout_wan"` - RejoinAfterLeave *bool `json:"rejoin_after_leave,omitempty" hcl:"rejoin_after_leave" mapstructure:"rejoin_after_leave"` - RetryJoinIntervalLAN *string `json:"retry_interval,omitempty" hcl:"retry_interval" mapstructure:"retry_interval"` - RetryJoinIntervalWAN *string `json:"retry_interval_wan,omitempty" hcl:"retry_interval_wan" mapstructure:"retry_interval_wan"` - RetryJoinLAN []string `json:"retry_join,omitempty" hcl:"retry_join" mapstructure:"retry_join"` - RetryJoinMaxAttemptsLAN *int `json:"retry_max,omitempty" hcl:"retry_max" mapstructure:"retry_max"` - RetryJoinMaxAttemptsWAN *int `json:"retry_max_wan,omitempty" hcl:"retry_max_wan" mapstructure:"retry_max_wan"` - RetryJoinWAN []string `json:"retry_join_wan,omitempty" hcl:"retry_join_wan" mapstructure:"retry_join_wan"` - SegmentName *string `json:"segment,omitempty" hcl:"segment" mapstructure:"segment"` - Segments []Segment `json:"segments,omitempty" hcl:"segments" mapstructure:"segments"` - SerfBindAddrLAN *string `json:"serf_lan,omitempty" hcl:"serf_lan" mapstructure:"serf_lan"` - SerfBindAddrWAN *string `json:"serf_wan,omitempty" hcl:"serf_wan" mapstructure:"serf_wan"` - ServerMode *bool `json:"server,omitempty" hcl:"server" mapstructure:"server"` - ServerName *string `json:"server_name,omitempty" hcl:"server_name" mapstructure:"server_name"` - Service *ServiceDefinition `json:"service,omitempty" hcl:"service" mapstructure:"service"` - Services []ServiceDefinition `json:"services,omitempty" hcl:"services" mapstructure:"services"` - SessionTTLMin *string `json:"session_ttl_min,omitempty" hcl:"session_ttl_min" mapstructure:"session_ttl_min"` - SkipLeaveOnInt *bool `json:"skip_leave_on_interrupt,omitempty" hcl:"skip_leave_on_interrupt" mapstructure:"skip_leave_on_interrupt"` - StartJoinAddrsLAN []string `json:"start_join,omitempty" hcl:"start_join" mapstructure:"start_join"` - StartJoinAddrsWAN []string `json:"start_join_wan,omitempty" hcl:"start_join_wan" mapstructure:"start_join_wan"` - SyslogFacility *string `json:"syslog_facility,omitempty" hcl:"syslog_facility" mapstructure:"syslog_facility"` - TLSCipherSuites *string `json:"tls_cipher_suites,omitempty" hcl:"tls_cipher_suites" mapstructure:"tls_cipher_suites"` - TLSMinVersion *string `json:"tls_min_version,omitempty" hcl:"tls_min_version" mapstructure:"tls_min_version"` - TLSPreferServerCipherSuites *bool `json:"tls_prefer_server_cipher_suites,omitempty" hcl:"tls_prefer_server_cipher_suites" mapstructure:"tls_prefer_server_cipher_suites"` - TaggedAddresses map[string]string `json:"tagged_addresses,omitempty" hcl:"tagged_addresses" mapstructure:"tagged_addresses"` - Telemetry Telemetry `json:"telemetry,omitempty" hcl:"telemetry" mapstructure:"telemetry"` - TranslateWANAddrs *bool `json:"translate_wan_addrs,omitempty" hcl:"translate_wan_addrs" mapstructure:"translate_wan_addrs"` - UI *bool `json:"ui,omitempty" hcl:"ui" mapstructure:"ui"` - UIDir *string `json:"ui_dir,omitempty" hcl:"ui_dir" mapstructure:"ui_dir"` - UnixSocket UnixSocket `json:"unix_sockets,omitempty" hcl:"unix_sockets" mapstructure:"unix_sockets"` - VerifyIncoming *bool `json:"verify_incoming,omitempty" hcl:"verify_incoming" mapstructure:"verify_incoming"` - VerifyIncomingHTTPS *bool `json:"verify_incoming_https,omitempty" hcl:"verify_incoming_https" mapstructure:"verify_incoming_https"` - VerifyIncomingRPC *bool `json:"verify_incoming_rpc,omitempty" hcl:"verify_incoming_rpc" mapstructure:"verify_incoming_rpc"` - VerifyOutgoing *bool `json:"verify_outgoing,omitempty" hcl:"verify_outgoing" mapstructure:"verify_outgoing"` - VerifyServerHostname *bool `json:"verify_server_hostname,omitempty" hcl:"verify_server_hostname" mapstructure:"verify_server_hostname"` - Watches []map[string]interface{} `json:"watches,omitempty" hcl:"watches" mapstructure:"watches"` + ACLAgentMasterToken *string `json:"acl_agent_master_token,omitempty" hcl:"acl_agent_master_token" mapstructure:"acl_agent_master_token"` + ACLAgentToken *string `json:"acl_agent_token,omitempty" hcl:"acl_agent_token" mapstructure:"acl_agent_token"` + ACLDatacenter *string `json:"acl_datacenter,omitempty" hcl:"acl_datacenter" mapstructure:"acl_datacenter"` + ACLDefaultPolicy *string `json:"acl_default_policy,omitempty" hcl:"acl_default_policy" mapstructure:"acl_default_policy"` + ACLDownPolicy *string `json:"acl_down_policy,omitempty" hcl:"acl_down_policy" mapstructure:"acl_down_policy"` + ACLEnableKeyListPolicy *bool `json:"acl_enable_key_list_policy,omitempty" hcl:"acl_enable_key_list_policy" mapstructure:"acl_enable_key_list_policy"` + ACLEnforceVersion8 *bool `json:"acl_enforce_version_8,omitempty" hcl:"acl_enforce_version_8" mapstructure:"acl_enforce_version_8"` + ACLMasterToken *string `json:"acl_master_token,omitempty" hcl:"acl_master_token" mapstructure:"acl_master_token"` + ACLReplicationToken *string `json:"acl_replication_token,omitempty" hcl:"acl_replication_token" mapstructure:"acl_replication_token"` + ACLTTL *string `json:"acl_ttl,omitempty" hcl:"acl_ttl" mapstructure:"acl_ttl"` + ACLToken *string `json:"acl_token,omitempty" hcl:"acl_token" mapstructure:"acl_token"` + Addresses Addresses `json:"addresses,omitempty" hcl:"addresses" mapstructure:"addresses"` + AdvertiseAddrLAN *string `json:"advertise_addr,omitempty" hcl:"advertise_addr" mapstructure:"advertise_addr"` + AdvertiseAddrWAN *string `json:"advertise_addr_wan,omitempty" hcl:"advertise_addr_wan" mapstructure:"advertise_addr_wan"` + Autopilot Autopilot `json:"autopilot,omitempty" hcl:"autopilot" mapstructure:"autopilot"` + BindAddr *string `json:"bind_addr,omitempty" hcl:"bind_addr" mapstructure:"bind_addr"` + Bootstrap *bool `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"` + BootstrapExpect *int `json:"bootstrap_expect,omitempty" hcl:"bootstrap_expect" mapstructure:"bootstrap_expect"` + CAFile *string `json:"ca_file,omitempty" hcl:"ca_file" mapstructure:"ca_file"` + CAPath *string `json:"ca_path,omitempty" hcl:"ca_path" mapstructure:"ca_path"` + CertFile *string `json:"cert_file,omitempty" hcl:"cert_file" mapstructure:"cert_file"` + Check *CheckDefinition `json:"check,omitempty" hcl:"check" mapstructure:"check"` // needs to be a pointer to avoid partial merges + CheckUpdateInterval *string `json:"check_update_interval,omitempty" hcl:"check_update_interval" mapstructure:"check_update_interval"` + Checks []CheckDefinition `json:"checks,omitempty" hcl:"checks" mapstructure:"checks"` + ClientAddr *string `json:"client_addr,omitempty" hcl:"client_addr" mapstructure:"client_addr"` + Connect Connect `json:"connect,omitempty" hcl:"connect" mapstructure:"connect"` + DNS DNS `json:"dns_config,omitempty" hcl:"dns_config" mapstructure:"dns_config"` + DNSDomain *string `json:"domain,omitempty" hcl:"domain" mapstructure:"domain"` + DNSRecursors []string `json:"recursors,omitempty" hcl:"recursors" mapstructure:"recursors"` + DataDir *string `json:"data_dir,omitempty" hcl:"data_dir" mapstructure:"data_dir"` + Datacenter *string `json:"datacenter,omitempty" hcl:"datacenter" mapstructure:"datacenter"` + DisableAnonymousSignature *bool `json:"disable_anonymous_signature,omitempty" hcl:"disable_anonymous_signature" mapstructure:"disable_anonymous_signature"` + DisableCoordinates *bool `json:"disable_coordinates,omitempty" hcl:"disable_coordinates" mapstructure:"disable_coordinates"` + DisableHostNodeID *bool `json:"disable_host_node_id,omitempty" hcl:"disable_host_node_id" mapstructure:"disable_host_node_id"` + DisableHTTPUnprintableCharFilter *bool `json:"disable_http_unprintable_char_filter,omitempty" hcl:"disable_http_unprintable_char_filter" mapstructure:"disable_http_unprintable_char_filter"` + DisableKeyringFile *bool `json:"disable_keyring_file,omitempty" hcl:"disable_keyring_file" mapstructure:"disable_keyring_file"` + DisableRemoteExec *bool `json:"disable_remote_exec,omitempty" hcl:"disable_remote_exec" mapstructure:"disable_remote_exec"` + DisableUpdateCheck *bool `json:"disable_update_check,omitempty" hcl:"disable_update_check" mapstructure:"disable_update_check"` + DiscardCheckOutput *bool `json:"discard_check_output" hcl:"discard_check_output" mapstructure:"discard_check_output"` + DiscoveryMaxStale *string `json:"discovery_max_stale" hcl:"discovery_max_stale" mapstructure:"discovery_max_stale"` + EnableACLReplication *bool `json:"enable_acl_replication,omitempty" hcl:"enable_acl_replication" mapstructure:"enable_acl_replication"` + EnableAgentTLSForChecks *bool `json:"enable_agent_tls_for_checks,omitempty" hcl:"enable_agent_tls_for_checks" mapstructure:"enable_agent_tls_for_checks"` + EnableDebug *bool `json:"enable_debug,omitempty" hcl:"enable_debug" mapstructure:"enable_debug"` + EnableScriptChecks *bool `json:"enable_script_checks,omitempty" hcl:"enable_script_checks" mapstructure:"enable_script_checks"` + EnableSyslog *bool `json:"enable_syslog,omitempty" hcl:"enable_syslog" mapstructure:"enable_syslog"` + EncryptKey *string `json:"encrypt,omitempty" hcl:"encrypt" mapstructure:"encrypt"` + EncryptVerifyIncoming *bool `json:"encrypt_verify_incoming,omitempty" hcl:"encrypt_verify_incoming" mapstructure:"encrypt_verify_incoming"` + EncryptVerifyOutgoing *bool `json:"encrypt_verify_outgoing,omitempty" hcl:"encrypt_verify_outgoing" mapstructure:"encrypt_verify_outgoing"` + HTTPConfig HTTPConfig `json:"http_config,omitempty" hcl:"http_config" mapstructure:"http_config"` + KeyFile *string `json:"key_file,omitempty" hcl:"key_file" mapstructure:"key_file"` + LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"` + Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"` + LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"` + NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"` + NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"` + NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"` + NonVotingServer *bool `json:"non_voting_server,omitempty" hcl:"non_voting_server" mapstructure:"non_voting_server"` + Performance Performance `json:"performance,omitempty" hcl:"performance" mapstructure:"performance"` + PidFile *string `json:"pid_file,omitempty" hcl:"pid_file" mapstructure:"pid_file"` + Ports Ports `json:"ports,omitempty" hcl:"ports" mapstructure:"ports"` + RPCProtocol *int `json:"protocol,omitempty" hcl:"protocol" mapstructure:"protocol"` + RaftProtocol *int `json:"raft_protocol,omitempty" hcl:"raft_protocol" mapstructure:"raft_protocol"` + RaftSnapshotThreshold *int `json:"raft_snapshot_threshold,omitempty" hcl:"raft_snapshot_threshold" mapstructure:"raft_snapshot_threshold"` + RaftSnapshotInterval *string `json:"raft_snapshot_interval,omitempty" hcl:"raft_snapshot_interval" mapstructure:"raft_snapshot_interval"` + ReconnectTimeoutLAN *string `json:"reconnect_timeout,omitempty" hcl:"reconnect_timeout" mapstructure:"reconnect_timeout"` + ReconnectTimeoutWAN *string `json:"reconnect_timeout_wan,omitempty" hcl:"reconnect_timeout_wan" mapstructure:"reconnect_timeout_wan"` + RejoinAfterLeave *bool `json:"rejoin_after_leave,omitempty" hcl:"rejoin_after_leave" mapstructure:"rejoin_after_leave"` + RetryJoinIntervalLAN *string `json:"retry_interval,omitempty" hcl:"retry_interval" mapstructure:"retry_interval"` + RetryJoinIntervalWAN *string `json:"retry_interval_wan,omitempty" hcl:"retry_interval_wan" mapstructure:"retry_interval_wan"` + RetryJoinLAN []string `json:"retry_join,omitempty" hcl:"retry_join" mapstructure:"retry_join"` + RetryJoinMaxAttemptsLAN *int `json:"retry_max,omitempty" hcl:"retry_max" mapstructure:"retry_max"` + RetryJoinMaxAttemptsWAN *int `json:"retry_max_wan,omitempty" hcl:"retry_max_wan" mapstructure:"retry_max_wan"` + RetryJoinWAN []string `json:"retry_join_wan,omitempty" hcl:"retry_join_wan" mapstructure:"retry_join_wan"` + SegmentName *string `json:"segment,omitempty" hcl:"segment" mapstructure:"segment"` + Segments []Segment `json:"segments,omitempty" hcl:"segments" mapstructure:"segments"` + SerfBindAddrLAN *string `json:"serf_lan,omitempty" hcl:"serf_lan" mapstructure:"serf_lan"` + SerfBindAddrWAN *string `json:"serf_wan,omitempty" hcl:"serf_wan" mapstructure:"serf_wan"` + ServerMode *bool `json:"server,omitempty" hcl:"server" mapstructure:"server"` + ServerName *string `json:"server_name,omitempty" hcl:"server_name" mapstructure:"server_name"` + Service *ServiceDefinition `json:"service,omitempty" hcl:"service" mapstructure:"service"` + Services []ServiceDefinition `json:"services,omitempty" hcl:"services" mapstructure:"services"` + SessionTTLMin *string `json:"session_ttl_min,omitempty" hcl:"session_ttl_min" mapstructure:"session_ttl_min"` + SkipLeaveOnInt *bool `json:"skip_leave_on_interrupt,omitempty" hcl:"skip_leave_on_interrupt" mapstructure:"skip_leave_on_interrupt"` + StartJoinAddrsLAN []string `json:"start_join,omitempty" hcl:"start_join" mapstructure:"start_join"` + StartJoinAddrsWAN []string `json:"start_join_wan,omitempty" hcl:"start_join_wan" mapstructure:"start_join_wan"` + SyslogFacility *string `json:"syslog_facility,omitempty" hcl:"syslog_facility" mapstructure:"syslog_facility"` + TLSCipherSuites *string `json:"tls_cipher_suites,omitempty" hcl:"tls_cipher_suites" mapstructure:"tls_cipher_suites"` + TLSMinVersion *string `json:"tls_min_version,omitempty" hcl:"tls_min_version" mapstructure:"tls_min_version"` + TLSPreferServerCipherSuites *bool `json:"tls_prefer_server_cipher_suites,omitempty" hcl:"tls_prefer_server_cipher_suites" mapstructure:"tls_prefer_server_cipher_suites"` + TaggedAddresses map[string]string `json:"tagged_addresses,omitempty" hcl:"tagged_addresses" mapstructure:"tagged_addresses"` + Telemetry Telemetry `json:"telemetry,omitempty" hcl:"telemetry" mapstructure:"telemetry"` + TranslateWANAddrs *bool `json:"translate_wan_addrs,omitempty" hcl:"translate_wan_addrs" mapstructure:"translate_wan_addrs"` + UI *bool `json:"ui,omitempty" hcl:"ui" mapstructure:"ui"` + UIDir *string `json:"ui_dir,omitempty" hcl:"ui_dir" mapstructure:"ui_dir"` + UnixSocket UnixSocket `json:"unix_sockets,omitempty" hcl:"unix_sockets" mapstructure:"unix_sockets"` + VerifyIncoming *bool `json:"verify_incoming,omitempty" hcl:"verify_incoming" mapstructure:"verify_incoming"` + VerifyIncomingHTTPS *bool `json:"verify_incoming_https,omitempty" hcl:"verify_incoming_https" mapstructure:"verify_incoming_https"` + VerifyIncomingRPC *bool `json:"verify_incoming_rpc,omitempty" hcl:"verify_incoming_rpc" mapstructure:"verify_incoming_rpc"` + VerifyOutgoing *bool `json:"verify_outgoing,omitempty" hcl:"verify_outgoing" mapstructure:"verify_outgoing"` + VerifyServerHostname *bool `json:"verify_server_hostname,omitempty" hcl:"verify_server_hostname" mapstructure:"verify_server_hostname"` + Watches []map[string]interface{} `json:"watches,omitempty" hcl:"watches" mapstructure:"watches"` // This isn't used by Consul but we've documented a feature where users // can deploy their snapshot agent configs alongside their Consul configs diff --git a/agent/config/runtime.go b/agent/config/runtime.go index d63c7e20d6df..dfb7893e0729 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -564,6 +564,16 @@ type RuntimeConfig struct { // flag: -disable-host-node-id DisableHostNodeID bool + // DisableHTTPUnprintableCharFilter will bypass the filter preventing HTTP + // URLs from containing unprintable chars. This filter was added in 1.0.3 as a + // response to a vulnerability report. Disabling this is never recommended in + // general however some users who have keys written in older versions of + // Consul may use this to temporarily disable the filter such that they can + // delete those keys again! We do not recommend leaving it disabled long term. + // + // hcl: disable_http_unprintable_char_filter + DisableHTTPUnprintableCharFilter bool + // DisableKeyringFile disables writing the keyring to a file. // // hcl: disable_keyring_file = (true|false) diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 9adc7f55f6fe..04a528b61810 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2622,6 +2622,7 @@ func TestFullConfig(t *testing.T) { "disable_anonymous_signature": true, "disable_coordinates": true, "disable_host_node_id": true, + "disable_http_unprintable_char_filter": true, "disable_keyring_file": true, "disable_remote_exec": true, "disable_update_check": true, @@ -3096,6 +3097,7 @@ func TestFullConfig(t *testing.T) { disable_anonymous_signature = true disable_coordinates = true disable_host_node_id = true + disable_http_unprintable_char_filter = true disable_keyring_file = true disable_remote_exec = true disable_update_check = true @@ -3701,75 +3703,76 @@ func TestFullConfig(t *testing.T) { "connect_timeout_ms": float64(1000), "pedantic_mode": true, }, - DNSAddrs: []net.Addr{tcpAddr("93.95.95.81:7001"), udpAddr("93.95.95.81:7001")}, - DNSARecordLimit: 29907, - DNSAllowStale: true, - DNSDisableCompression: true, - DNSDomain: "7W1xXSqd", - DNSEnableTruncate: true, - DNSMaxStale: 29685 * time.Second, - DNSNodeTTL: 7084 * time.Second, - DNSOnlyPassing: true, - DNSPort: 7001, - DNSRecursorTimeout: 4427 * time.Second, - DNSRecursors: []string{"63.38.39.58", "92.49.18.18"}, - DNSServiceTTL: map[string]time.Duration{"*": 32030 * time.Second}, - DNSUDPAnswerLimit: 29909, - DNSNodeMetaTXT: true, - DataDir: dataDir, - Datacenter: "rzo029wg", - DevMode: true, - DisableAnonymousSignature: true, - DisableCoordinates: true, - DisableHostNodeID: true, - DisableKeyringFile: true, - DisableRemoteExec: true, - DisableUpdateCheck: true, - DiscardCheckOutput: true, - DiscoveryMaxStale: 5 * time.Second, - EnableACLReplication: true, - EnableAgentTLSForChecks: true, - EnableDebug: true, - EnableScriptChecks: true, - EnableSyslog: true, - EnableUI: true, - EncryptKey: "A4wELWqH", - EncryptVerifyIncoming: true, - EncryptVerifyOutgoing: true, - HTTPAddrs: []net.Addr{tcpAddr("83.39.91.39:7999")}, - HTTPBlockEndpoints: []string{"RBvAFcGD", "fWOWFznh"}, - HTTPPort: 7999, - HTTPResponseHeaders: map[string]string{"M6TKa9NP": "xjuxjOzQ", "JRCrHZed": "rl0mTx81"}, - HTTPSAddrs: []net.Addr{tcpAddr("95.17.17.19:15127")}, - HTTPSPort: 15127, - KeyFile: "IEkkwgIA", - LeaveDrainTime: 8265 * time.Second, - LeaveOnTerm: true, - LogLevel: "k1zo9Spt", - NodeID: types.NodeID("AsUIlw99"), - NodeMeta: map[string]string{"5mgGQMBk": "mJLtVMSG", "A7ynFMJB": "0Nx6RGab"}, - NodeName: "otlLxGaI", - NonVotingServer: true, - PidFile: "43xN80Km", - RPCAdvertiseAddr: tcpAddr("17.99.29.16:3757"), - RPCBindAddr: tcpAddr("16.99.34.17:3757"), - RPCHoldTimeout: 15707 * time.Second, - RPCProtocol: 30793, - RPCRateLimit: 12029.43, - RPCMaxBurst: 44848, - RaftProtocol: 19016, - RaftSnapshotThreshold: 16384, - RaftSnapshotInterval: 30 * time.Second, - ReconnectTimeoutLAN: 23739 * time.Second, - ReconnectTimeoutWAN: 26694 * time.Second, - RejoinAfterLeave: true, - RetryJoinIntervalLAN: 8067 * time.Second, - RetryJoinIntervalWAN: 28866 * time.Second, - RetryJoinLAN: []string{"pbsSFY7U", "l0qLtWij"}, - RetryJoinMaxAttemptsLAN: 913, - RetryJoinMaxAttemptsWAN: 23160, - RetryJoinWAN: []string{"PFsR02Ye", "rJdQIhER"}, - SegmentName: "BC2NhTDi", + DNSAddrs: []net.Addr{tcpAddr("93.95.95.81:7001"), udpAddr("93.95.95.81:7001")}, + DNSARecordLimit: 29907, + DNSAllowStale: true, + DNSDisableCompression: true, + DNSDomain: "7W1xXSqd", + DNSEnableTruncate: true, + DNSMaxStale: 29685 * time.Second, + DNSNodeTTL: 7084 * time.Second, + DNSOnlyPassing: true, + DNSPort: 7001, + DNSRecursorTimeout: 4427 * time.Second, + DNSRecursors: []string{"63.38.39.58", "92.49.18.18"}, + DNSServiceTTL: map[string]time.Duration{"*": 32030 * time.Second}, + DNSUDPAnswerLimit: 29909, + DNSNodeMetaTXT: true, + DataDir: dataDir, + Datacenter: "rzo029wg", + DevMode: true, + DisableAnonymousSignature: true, + DisableCoordinates: true, + DisableHostNodeID: true, + DisableHTTPUnprintableCharFilter: true, + DisableKeyringFile: true, + DisableRemoteExec: true, + DisableUpdateCheck: true, + DiscardCheckOutput: true, + DiscoveryMaxStale: 5 * time.Second, + EnableACLReplication: true, + EnableAgentTLSForChecks: true, + EnableDebug: true, + EnableScriptChecks: true, + EnableSyslog: true, + EnableUI: true, + EncryptKey: "A4wELWqH", + EncryptVerifyIncoming: true, + EncryptVerifyOutgoing: true, + HTTPAddrs: []net.Addr{tcpAddr("83.39.91.39:7999")}, + HTTPBlockEndpoints: []string{"RBvAFcGD", "fWOWFznh"}, + HTTPPort: 7999, + HTTPResponseHeaders: map[string]string{"M6TKa9NP": "xjuxjOzQ", "JRCrHZed": "rl0mTx81"}, + HTTPSAddrs: []net.Addr{tcpAddr("95.17.17.19:15127")}, + HTTPSPort: 15127, + KeyFile: "IEkkwgIA", + LeaveDrainTime: 8265 * time.Second, + LeaveOnTerm: true, + LogLevel: "k1zo9Spt", + NodeID: types.NodeID("AsUIlw99"), + NodeMeta: map[string]string{"5mgGQMBk": "mJLtVMSG", "A7ynFMJB": "0Nx6RGab"}, + NodeName: "otlLxGaI", + NonVotingServer: true, + PidFile: "43xN80Km", + RPCAdvertiseAddr: tcpAddr("17.99.29.16:3757"), + RPCBindAddr: tcpAddr("16.99.34.17:3757"), + RPCHoldTimeout: 15707 * time.Second, + RPCProtocol: 30793, + RPCRateLimit: 12029.43, + RPCMaxBurst: 44848, + RaftProtocol: 19016, + RaftSnapshotThreshold: 16384, + RaftSnapshotInterval: 30 * time.Second, + ReconnectTimeoutLAN: 23739 * time.Second, + ReconnectTimeoutWAN: 26694 * time.Second, + RejoinAfterLeave: true, + RetryJoinIntervalLAN: 8067 * time.Second, + RetryJoinIntervalWAN: 28866 * time.Second, + RetryJoinLAN: []string{"pbsSFY7U", "l0qLtWij"}, + RetryJoinMaxAttemptsLAN: 913, + RetryJoinMaxAttemptsWAN: 23160, + RetryJoinWAN: []string{"PFsR02Ye", "rJdQIhER"}, + SegmentName: "BC2NhTDi", Segments: []structs.NetworkSegment{ { Name: "PExYMe2E", @@ -4436,6 +4439,7 @@ func TestSanitize(t *testing.T) { "DevMode": false, "DisableAnonymousSignature": false, "DisableCoordinates": false, + "DisableHTTPUnprintableCharFilter": false, "DisableHostNodeID": false, "DisableKeyringFile": false, "DisableRemoteExec": false, diff --git a/agent/http.go b/agent/http.go index 1cce524af1ea..1f891953956f 100644 --- a/agent/http.go +++ b/agent/http.go @@ -187,10 +187,15 @@ func (s *HTTPServer) handler(enableDebug bool) http.Handler { } // Wrap the whole mux with a handler that bans URLs with non-printable - // characters. + // characters, unless disabled explicitly to deal with old keys that fail this + // check. + h := cleanhttp.PrintablePathCheckHandler(mux, nil) + if s.agent.config.DisableHTTPUnprintableCharFilter { + h = mux + } return &wrappedMux{ mux: mux, - handler: cleanhttp.PrintablePathCheckHandler(mux, nil), + handler: h, } } diff --git a/agent/http_test.go b/agent/http_test.go index 42e0eec55c9f..ffe560d1249f 100644 --- a/agent/http_test.go +++ b/agent/http_test.go @@ -327,6 +327,19 @@ func TestHTTPAPI_Ban_Nonprintable_Characters(t *testing.T) { } } +func TestHTTPAPI_Allow_Nonprintable_Characters_With_Flag(t *testing.T) { + a := NewTestAgent(t.Name(), "disable_http_unprintable_char_filter = true") + defer a.Shutdown() + + req, _ := http.NewRequest("GET", "/v1/kv/bad\x00ness", nil) + resp := httptest.NewRecorder() + a.srv.Handler.ServeHTTP(resp, req) + // Key doesn't actually exist so we should get 404 + if got, want := resp.Code, http.StatusNotFound; got != want { + t.Fatalf("bad response code got %d want %d", got, want) + } +} + func TestHTTPAPI_TranslateAddrHeader(t *testing.T) { t.Parallel() // Header should not be present if address translation is off. diff --git a/website/source/docs/agent/options.html.md b/website/source/docs/agent/options.html.md index ed66e8e3a8ef..75029f63da06 100644 --- a/website/source/docs/agent/options.html.md +++ b/website/source/docs/agent/options.html.md @@ -764,6 +764,17 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass * `disable_host_node_id` Equivalent to the [`-disable-host-node-id` command-line flag](#_disable_host_node_id). +* `disable_http_unprintable_char_filter` + Defaults to false. Consul 1.0.3 fixed a potential security vulnerability where + malicious users could craft KV keys with unprintable chars that would confuse + operators using the CLI or UI into taking wrong actions. Users who had data + written in older versions of Consul that did not have this restriction will be + unable to delete those values by default in 1.0.3 or later. This setting + enables those users to _temporarily_ disable the filter such that delete + operations can work on those keys again to get back to a healthy state. It is + strongly recommended that this filter is not disabled permanently as it + exposes the original security vulnerability. + * `disable_remote_exec` Disables support for remote execution. When set to true, the agent will ignore any incoming remote exec requests. In versions of Consul prior to 0.8, this defaulted to false. In Consul