[BUG] "Invalid IPv6 URL" when providing an invalid state name to state.apply
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 15.7k
- Forks
- 5.6k
- Avg merge
- 2d 44m
- Merged PRs (30d)
- 80
Description
Description
When providing certain bad arguments to state.apply, the execution will fail with a ValueError and nothing easily actionable by the user. E.g.:
salt-call state.apply '\["some.state"\]'
This will raise an exception:
ValueError: Invalid IPv6 URL
Although this seems a bit contrived, it's easier to stumble on when using salt-api where it can be easy to lose track of the right magic required to supply the arg value, e.g.:
curl -sSk https://localhost:8000/ -H 'Accept: application/x-yaml' ... -d fun='state.sls' -d arg='["some.state"]'
Setup
As above.
Steps to Reproduce the behavior
As above. Debug logs below. I added one log by changing https://github.com/saltstack/salt/blob/da6819735ce055f16e326472cb1768faece72ad6/salt/fileclient.py#L478 to:
try:
url_data = urlparse(url)
except ValueError:
log.debug("URL was: %s", url)
raise
[DEBUG ] URL was: salt://\["some/state"\].sls
full debug log
[DEBUG ] Reading configuration from /etc/salt/minion
[DEBUG ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG ] Configuration file path: /etc/salt/minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG ] Grains refresh requested. Refreshing grains.
[DEBUG ] Reading configuration from /etc/salt/minion
[DEBUG ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG ] Elapsed time getting FQDNs: 0.008494853973388672 seconds
[DEBUG ] LazyLoaded zfs.is_supported
[DEBUG ] Connecting to master. Attempt 1 of 1
[DEBUG ] "master1" Not an IP address? Assuming it is a hostname.
[DEBUG ] Master URI: tcp://192.168.144.2:4506
[DEBUG ] Initializing new AsyncAuth for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506')
[DEBUG ] Generated random reconnect delay between '1000ms' and '11000ms' (10132)
[DEBUG ] Setting zmq_reconnect_ivl to '10132ms'
[DEBUG ] Setting zmq_reconnect_ivl_max to '11000ms'
[DEBUG ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506', 'clear')
[DEBUG ] Connecting the Minion to the Master URI (for the return server): tcp://192.168.144.2:4506
[DEBUG ] Trying to connect to: tcp://192.168.144.2:4506
[DEBUG ] salt.crypt.get_rsa_pub_key: Loading public key
[DEBUG ] Decrypting the current master AES key
[DEBUG ] salt.crypt.get_rsa_key: Loading private key
[DEBUG ] salt.crypt._get_key_with_evict: Loading private key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] salt.crypt.get_rsa_pub_key: Loading public key
[DEBUG ] Closing AsyncZeroMQReqChannel instance
[DEBUG ] Connecting the Minion to the Master publish port, using the URI: tcp://192.168.144.2:4505
[DEBUG ] salt.crypt.get_rsa_key: Loading private key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Determining pillar cache
[DEBUG ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506', 'aes')
[DEBUG ] Initializing new AsyncAuth for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506')
[DEBUG ] Connecting the Minion to the Master URI (for the return server): tcp://192.168.144.2:4506
[DEBUG ] Trying to connect to: tcp://192.168.144.2:4506
[DEBUG ] salt.crypt.get_rsa_key: Loading private key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Closing AsyncZeroMQReqChannel instance
[DEBUG ] LazyLoaded jinja.render
[DEBUG ] LazyLoaded yaml.render
[DEBUG ] LazyLoaded state.apply
[DEBUG ] LazyLoaded direct_call.execute
[DEBUG ] LazyLoaded saltutil.is_running
[DEBUG ] LazyLoaded grains.get
[DEBUG ] LazyLoaded config.get
[DEBUG ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506', 'aes')
[DEBUG ] Initializing new AsyncAuth for ('/etc/salt/pki/minion', 'master1', 'tcp://192.168.144.2:4506')
[DEBUG ] Connecting the Minion to the Master URI (for the return server): tcp://192.168.144.2:4506
[DEBUG ] Trying to connect to: tcp://192.168.144.2:4506
[DEBUG ] Gathering pillar data for state run
[DEBUG ] Finished gathering pillar data for state run
[INFO ] Loading fresh modules for state activity
[DEBUG ] LazyLoaded jinja.render
[DEBUG ] LazyLoaded yaml.render
[DEBUG ] URL was: salt://\["some/state"\].sls
[DEBUG ] Closing AsyncZeroMQReqChannel instance
[ERROR ] An un-handled exception was caught by salt's global exception handler:
ValueError: Invalid IPv6 URL
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
load_entry_point('salt==3002.2', 'console_scripts', 'salt-call')()
File "/usr/lib/python3/dist-packages/salt/scripts.py", line 449, in salt_call
client.run()
File "/usr/lib/python3/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 112, in run
ret = self.call()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 219, in call
ret["return"] = self.minion.executors[fname](
File "/usr/lib/python3/dist-packages/salt/executors/direct_call.py", line 12, in execute
return func(*args, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/state.py", line 800, in apply_
return sls(mods, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/state.py", line 1386, in sls
high_, errors = st_.render_highstate({opts["saltenv"]: mods})
File "/usr/lib/python3/dist-packages/salt/state.py", line 4300, in render_highstate
state, errors = self.render_state(
File "/usr/lib/python3/dist-packages/salt/state.py", line 3942, in render_state
state_data = self.client.get_state(sls, saltenv)
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 399, in get_state
dest = self.cache_file(path, saltenv, cachedir=cachedir)
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 186, in cache_file
return self.get_url(
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 479, in get_url
url_data = urlparse(url)
File "/usr/lib/python3.8/urllib/parse.py", line 373, in urlparse
splitresult = urlsplit(url, scheme, allow_fragments)
File "/usr/lib/python3.8/urllib/parse.py", line 464, in urlsplit
raise ValueError("Invalid IPv6 URL")
ValueError: Invalid IPv6 URL
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
load_entry_point('salt==3002.2', 'console_scripts', 'salt-call')()
File "/usr/lib/python3/dist-packages/salt/scripts.py", line 449, in salt_call
client.run()
File "/usr/lib/python3/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 112, in run
ret = self.call()
File "/usr/lib/python3/dist-packages/salt/cli/caller.py", line 219, in call
ret["return"] = self.minion.executors[fname](
File "/usr/lib/python3/dist-packages/salt/executors/direct_call.py", line 12, in execute
return func(*args, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/state.py", line 800, in apply_
return sls(mods, **kwargs)
File "/usr/lib/python3/dist-packages/salt/modules/state.py", line 1386, in sls
high_, errors = st_.render_highstate({opts["saltenv"]: mods})
File "/usr/lib/python3/dist-packages/salt/state.py", line 4300, in render_highstate
state, errors = self.render_state(
File "/usr/lib/python3/dist-packages/salt/state.py", line 3942, in render_state
state_data = self.client.get_state(sls, saltenv)
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 399, in get_state
dest = self.cache_file(path, saltenv, cachedir=cachedir)
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 186, in cache_file
return self.get_url(
File "/usr/lib/python3/dist-packages/salt/fileclient.py", line 479, in get_url
url_data = urlparse(url)
File "/usr/lib/python3.8/urllib/parse.py", line 373, in urlparse
splitresult = urlsplit(url, scheme, allow_fragments)
File "/usr/lib/python3.8/urllib/parse.py", line 464, in urlsplit
raise ValueError("Invalid IPv6 URL")
ValueError: Invalid IPv6 URL
Expected behavior
More informative errors and/or logs.
Versions Report
salt --versions-report
Salt Version:
Salt: 3002.2
Dependency Versions:
cffi: 1.14.4
cherrypy: unknown
dateutil: 2.7.3
docker-py: Not Installed
gitdb: 2.0.6
gitpython: 3.0.7
Jinja2: 2.10.1
libgit2: Not Installed
M2Crypto: Not Installed
Mako: Not Installed
msgpack: 0.6.2
msgpack-pure: Not Installed
mysql-python: Not Installed
pycparser: 2.20
pycrypto: 2.6.1
pycryptodome: 3.6.1
pygit2: Not Installed
Python: 3.8.5 (default, Jul 28 2020, 12:59:40)
python-gnupg: 0.4.5
PyYAML: 5.3.1
PyZMQ: 18.1.1
smmap: 2.0.5
timelib: Not Installed
Tornado: 4.5.3
ZMQ: 4.3.2
System Versions:
dist: ubuntu 20.04 focal
locale: utf-8
machine: x86_64
release: 5.4.0-54-generic
system: Linux
version: Ubuntu 20.04 focal
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in salt/fileclient.py at the urlparse call around line 478 and trace how the invalid state name reaches get_url from salt/modules/state.py. Reproduce the salt-call state.apply example, then make the resulting error or logs actionable and verify the behavior with the relevant existing fileclient or state tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100