From d6c16dd0adc359e57964be638a00c47559af8240 Mon Sep 17 00:00:00 2001 From: Paul Banks Date: Wed, 25 Jul 2018 15:52:37 +0100 Subject: [PATCH] Add config option to disable HTTP printable char path check --- 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 940e6f207..34125ac1c 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -690,6 +690,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 c54090b3f..0baf45325 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 d63c7e20d..dfb7893e0 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 c81ed7e3a..def6246d6 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2621,6 +2621,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, @@ -3084,6 +3085,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 @@ -3678,75 +3680,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", @@ -4403,6 +4406,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 1cce524af..1f8919539 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 42e0eec55..ffe560d12 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 8d7894d3c..7aa463496 100644 --- a/website/source/docs/agent/options.html.md +++ b/website/source/docs/agent/options.html.md @@ -749,6 +749,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