Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix input/output streams for gpg validation #1057

Closed
wants to merge 1 commit into from

Conversation

cdoern
Copy link
Contributor

@cdoern cdoern commented Jun 2, 2022

currently, our gpg function which uses exec.Command to gpg --encrypt and
gpg --decrypt does not allow for stdin or out to be anything but a buffer stream directly used in the program
this causes gpg to error out since it cannot ask for validation on locked keys.
Fix this by passing stdin to --decrypt as the "in" var and stdout as the "out" var to --encrypt

resolves containers/podman#13539

Signed-off-by: cdoern cdoern@redhat.com

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jun 2, 2022

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: cdoern
To complete the pull request process, please assign baude after the PR has been reviewed.
You can assign the PR to them by writing /assign @baude in a comment when ready.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@cdoern
Copy link
Contributor Author

cdoern commented Jun 2, 2022

@ashley-cui PTAL

Copy link
Member

@ashley-cui ashley-cui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM! Just seeing if we can test with a locked gpg key. Going to have to trust you on the hardware token part since I don't have a hardware key

@@ -28,6 +28,9 @@ func setupDriver(t *testing.T) (driver *Driver, cleanup func()) {
err = driver.gpg(context.TODO(), nil, nil, "--batch", "--passphrase", "--quick-generate-key", "testing@passdriver")
require.NoError(t, err)

err = driver.gpg(context.TODO(), os.Stdin, os.Stderr, "--batch", "--passphrase", "--quick-generate-key", "testing@passdriver")
require.NoError(t, err)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to test this with a key that has a password?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I was not sure how to approach this. if we could somehow ensure that pass is installed i could test it really easily but it was not installed on my fedora machine. Is there a way to dnf install stuff in these tests?

cc/ @edsantiago

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need pass installed for the passdriver to work, only gpg. Maybe look into generating a key that has a password? And maybe a gpg flag to pass in the password when decrypting the key?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the full context here, but (1) no you can't dnf-install, (2) have you considered --passphrase-file?

@cdoern cdoern force-pushed the passDriver branch 2 times, most recently from e621472 to a599662 Compare June 3, 2022 13:57
@cdoern
Copy link
Contributor Author

cdoern commented Jun 3, 2022

@ashley-cui PTAL I think thats the most applicable test I can make for this.

@@ -25,12 +25,15 @@ func setupDriver(t *testing.T) (driver *Driver, cleanup func()) {
})
require.NoError(t, err)

err = driver.gpg(context.TODO(), nil, nil, "--batch", "--passphrase", "--quick-generate-key", "testing@passdriver")
f, err := ioutil.TempFile("", "pass.txt")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm just taking a quick look. Did you mean to actually write some sort of passphrase into the file? If so have I missed where that happens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @edsantiago I think I missed a line here. I will circle back to this today

@cdoern cdoern force-pushed the passDriver branch 2 times, most recently from 98cfad7 to 4322730 Compare June 10, 2022 19:33
currently, our gpg function which uses exec.Command to `gpg --encrypt` and
`gpg --decrypt` does not allow for stdin or out to be anything but a buffer stream directly used in the program
this causes `gpg` to error out since it cannot ask for validation on locked keys.
Fix this by passing stdin to --decrypt as the "in" var and stdout as the "out" var to --encrypt

resolves containers/podman#13539

Signed-off-by: cdoern <cdoern@redhat.com>
@edsantiago
Copy link
Collaborator

CI failure seems persistent (i.e., not a flake)

@rhatdan
Copy link
Member

rhatdan commented Jun 21, 2022

@cdoern whats up with this one?

@cdoern
Copy link
Contributor Author

cdoern commented Jun 21, 2022

I am working on this one now, trying to figure out how to give the TestLookup test a dummy stdin

@cdoern
Copy link
Contributor Author

cdoern commented Jun 21, 2022

@edsantiago any idea here how to get the test to acknowledge stdin? I tried just writing "123" to a file and setting os.Stdin = f but that just times out and the commands do not have the proper input

@edsantiago
Copy link
Collaborator

@cdoern I can't see the code you're referring to; I assume it's unpushed and will guess that your question is: "how do I run gpg, from within go, such that its stdin is something of my choice". I don't know enough go to answer that, but the traditional approach has been to fork(), switch filehandles (e.g. reopen os.Stdin), then exec(). There is almost certainly an idiomatic go way to do this but that's a question for those more literate.

@cdoern
Copy link
Contributor Author

cdoern commented Jun 21, 2022

@edsantiago sorry for the vague question. I figured out a way to modify the code here to pass lookup a byte array and if that is nil, default to stdin.

@cdoern
Copy link
Contributor Author

cdoern commented Jun 22, 2022

been working on this for a bit, keep walking in circles with trying to wire up the stdin/out @ashley-cui is there any reason we would not want actual stdin/out here? the code seems to be fighting me a lot on this change.

@ashley-cui
Copy link
Member

I'm not sure, since it looks like the gpg() function is just a cmd.exec, so it makes sense that. a regular os.stdin/os.stdout would work. Have you looked at if its specifically stdin or stdout that's not behaving, or do both have issues?

@openshift-merge-robot
Copy link
Collaborator

@cdoern: PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@mtrmac
Copy link
Collaborator

mtrmac commented Jul 30, 2022

@cdoern FWIW I wouldn’t expect just redirecting stdin to typically work. GPG is not just reading from stdin, it has a concept of pinentry which intends to talk to the user regardless of stdin. That might be using /dev/tty, or perhaps even popping a GUI window completely outside of any terminal.

That behavior needs to be explicitly opted out, in particular the documentation of --passphrase-file points at --pinentry-mode loopback.

@cdoern
Copy link
Contributor Author

cdoern commented Aug 11, 2022

wouldn’t expect just redirecting stdin to typically work. GPG is not just reading from stdin, it has a concept of pinentry which intends to talk to the user regardless of stdin. That might be using /dev/tty, or perhaps even popping a GUI window completely outside
@mtrmac, strangely enough when testing this locally, changing to stdin does fix the issue. I really cant pinpoint why or hot though which is why this has languished for so long. Either way, setting to nil it definitely what is breaking this right now. Any tips?

@mtrmac
Copy link
Collaborator

mtrmac commented Aug 15, 2022

That really depends on various details of the specific runtime environment of the process (e.g. is there a login session, is there a controlling TTY known to the kernel, is there an environment variable pointing at a pre-existing GPG agent).

I could well imagine that an isolated process with no session and no TTY tries to auto-start the GPG agent, and just fails because it has no way to communicate with the user; while passing a stdin TTY allows the GPG agent to run.


I don’t have much of a recommendation for understanding what’s going on beyond strace.

I would have recommended using GPGME instead of manually running GPG commands, but ultimately GPGME runs these commands as well, so that’s not helpful for the current situation — it would only add one more layer of indirection to unravel.

@vrothberg
Copy link
Member

Closing due to inactivity.

@vrothberg vrothberg closed this May 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

podman secrets --driver=pass hardware token
7 participants