Allow the credentials to be given as files rather than as env vars - #31
tigerblue77 wants to merge 2 commits into
Conversation
adduser and chpasswd could both fail without the script noticing, and it went
on to write the role map and exec /sbin/init regardless. The container then
came up healthy, OMSA answered on 1311, and the login simply did not work --
with the reason eight lines above in a log nobody reads when the web UI is
already up.
Both are now checked, and either failing stops the container with a message
saying which one it was.
The "--" on getent and adduser is the same failure reached another way. Without
it a username beginning with "-" is read as an option rather than as a name:
"getent passwd -x" answers "invalid option -- 'x'" and exits 64 rather than
"no such user", so the lookup fails for the wrong reason, and "adduser -x"
then exits 2 on the same complaint. With "--" the name reaches validation and
useradd says what is actually wrong with it ("invalid user name '-x'", exit 3),
which the check above now turns into a clean exit rather than a container that
starts anyway.
printf replaces echo for the same class of reason: echo has no portable way of
being told to stop looking for options, so a username beginning with "-n" or
"-e" is eaten as one instead of reaching chpasswd.
Verified by running the script before and after against mocked getent, adduser,
chpasswd and init. With adduser refusing, before: "INIT REACHED", exit 0, no
account, role map written. After: exit 1, nothing written. Same for chpasswd
refusing. The ordinary path is byte for byte what it was.
Signed-off-by: Tigerblue77 <37409593+tigerblue77@users.noreply.github.com>
OMSA_PASS stays readable for the life of the container: "docker inspect" prints it, /proc/<pid>/environ inside the container has it, and anything that dumps the environment on a crash takes it along. That is unavoidable for a value passed as "-e", and it is the one thing a file does not have. OMSA_USER_FILE and OMSA_PASS_FILE are added beside the existing variables rather than instead of them, so nothing that works today changes. "/run/secrets/<name>" is where compose and swarm put a secret, so no plumbing is needed past naming it. Setting both an env var and its _FILE is refused rather than one silently winning, which is the failure that is otherwise found months later by wondering which of the two the container is actually using. An unreadable file stops the container rather than falling through to "please specify OMSA_USER and OMSA_PASS", which would be true and useless. Only the first line of the file is used, with its newline stripped -- what "echo" and "docker secret create" from a here-string produce. A password containing a newline cannot go through a file; the env var still takes anything. One consequence worth pointing at rather than leaving to be discovered: the re-create recipe in the README reads the credentials back out of the running container's environment, which is the very thing this avoids. A container started from a secret has to be given the secret again instead, and the README now says so beside the example. Verified against mocked getent, adduser, chpasswd and init: both credentials from files, either one from a file, both an env var and its _FILE set, an unreadable file, neither given, and a password containing a colon (chpasswd splits on the first one, so it survives). The env-var-only path is unchanged. Signed-off-by: Tigerblue77 <37409593+tigerblue77@users.noreply.github.com>
|
I generally like this idea, so I've rewritten it and added it (8edc5dc) I'd prefer commits were marked as authored by you, even if you used Claude or some other AI tooling to do (most of) it - I see the AI as a tool not a code author. Something like Assisted-by (like https://docs.kernel.org/process/coding-assistants.html) would be fine, but not author or signed-off-by. |
|
No complaint at all — your version is better than mine in the place it matters, and I went looking before saying so. Refusing a username that begins with I ran the suite from #35 against Two things I looked at and am deliberately not raising as issues, so that "I found nothing" is not just silence: Thanks for taking the idea rather than the patch — that is the better outcome for a file you have to maintain. |
This is the one that adds rather than fixes, so it is where your judgement matters most and mine matters least. The case for it:
OMSA_PASSis readable for the life of the container by anything that can rundocker inspector read/proc/<pid>/environ, which is unavoidable for a value passed as-eand is the one thing a file does not have. Twenty lines, no behaviour change for anyone who keeps using the environment variables, and it is what makes this image deployable under compose or swarm secrets without the password sitting in the clear.This is the stacked shape you pointed at on #28: it and the
run.shPR touch the same part of the file, so this branch contains that commit too. Merge that one first and this becomes a one-commit diff.OMSA_PASSstays readable for the life of the container:docker inspectprints it,/proc/<pid>/environinside the container has it, and anything that dumps the environment on a crash takes it along. That is unavoidable for a value passed as-e, and is the one thing a file does not have.OMSA_USER_FILEandOMSA_PASS_FILEare added beside the existing variables, not instead of them, so nothing that works today changes./run/secrets/<name>is where compose and swarm put a secret, so there is no plumbing past naming it.Setting both an env var and its
_FILEis refused rather than one silently winning. An unreadable file stops the container rather than falling through to "please specify OMSA_USER and OMSA_PASS", which would be true and useless.Only the first line is used, newline stripped -- what
echoanddocker secret createfrom a here-string produce. A password containing a newline cannot go through a file; the env var still takes anything.One consequence worth pointing at rather than leaving to be found: the re-create recipe in the README reads the credentials back out of the running container's environment, which is the very thing this avoids. A container started from a secret has to be given the secret again instead. The README says so beside the new example.
Verification
Run against mocked
getent,adduser,chpasswdandinit: both credentials from files, either one from a file, both an env var and its_FILEset (refused), an unreadable file (refused), neither given (refused), a password containing a colon (survives --chpasswdsplits on the first one), and the env-var-only path unchanged.shellcheck -xclean.About the authorship
Per your answer on #28. The commit is authored by Claude and carries my
Signed-off-by:, which is how I record this in my own repositories: the agent wrote it, sogit logandgit blamesay so, and the sign-off names the person who read it and stands behind it. That person is me -- I have read every line, the reasoning above is mine, and any question you ask about it gets answered by me and not by a re-prompt.The branch is based on
487c4eb(thev0.4.0tag), so it is up to date withmasterand merges clean.