I cannot use Go nor Python etcd APIs to perform interaction with etcd.
I need to query:
env ETCDCTL_API=3 etcdctl --endpoints=server:2379 --cert ca.pem --key ca.key --cacert cacert.pem --command-timeout=60s get $(echo L3ZvdGUvADHd0kmW58d9JqTD8whMYS9vY3Nw | base64 -d)
This will return:
-bash: warning: command substitution: ignored null byte in input
However running alone:
echo L3ZvdGUvADHd0kmW58d9JqTD8whMYS9vY3Nw | base64 -d
Returns:
/vote/1��I���}&��La/ocsp
What is the problem and how could I maybe escape, but still remain valid key for etcd and GET query it?
Unfortunately, unless etcdctl
is extended to explicitly support accepting escaped contents, and unescaping that content to get the key name to use (or to accept key names passed via a means other than the command line), passing a key name containing a literal NUL is not possible.
Consider writing your own command-line client for etcd that accepts encoded strings if this is something you need to do.
When a program starts another program on UNIX, the process involves a syscall called execve()
(or an equivalent: there are higher-level tools like the POSIX spawn() family, but they still act similarly for our purposes here). This might look like:
pid = execve("/usr/bin/etcd", char[][]{
"etcd",
"--endpoints=server:2379",
/* other content here elided */
"get",
keyname
}, environment)
Because this API is defined in C, all strings are NUL-terminated C strings; they start at the character that an individual char*
points to, and end at the next NUL after that character (so when you type "get"
in C, it creates an array like {"g", "e", "t", NULL}
).
Thus, if you have something that actually looks like {"g", "e", "t", NULL, "f", "o", "o", NULL}
, only get
is part of the string starting to the g
; there needs to be another pointer to the f
in foo
for foo
to be seen as a separate argument, and there's no possible way for get\x00foo
to be seen as a single string with \x00
representing a single-byte NUL literal by anything written to interact with C-style strings.