-
Notifications
You must be signed in to change notification settings - Fork 831
Add support for GPG #59
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
Conversation
|
Two successful matrix test runs: You can view the |
__tests__/auth.test.ts
Outdated
| <activeByDefault>true</activeByDefault> | ||
| </activation> | ||
| <properties> | ||
| <gpg.passphrase>\${env.${gpgPassphrase}}</gpg.passphrase> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
putting this in a server section is more in line with the recommended setup at http://maven.apache.org/plugins/maven-gpg-plugin/usage.html#Configure_passphrase_in_settings.xml and also later on would allow for storing it in an encrypted fashion. Having it in a default profile as property is just too much overhead IMHO.
|
Updated Two successful matrix test runs: View the View the |
|
@joshmgross Can you take a look at this PR or let me know who the appropriate reviewer should be? Thanks! |
|
Thanks for the ping @jaredpetersen, I'll take a look at this today. |
| export const DEFAULT_USERNAME = 'GITHUB_ACTOR'; | ||
| export const DEFAULT_PASSWORD = 'GITHUB_TOKEN'; | ||
| export const DEFAULT_GPG_PRIVATE_KEY = ''; | ||
| export const DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we default to an empty string here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does default to an empty string. Just like GITHUB_TOKEN and GITHUB_ACTOR are environment variables, GPG_PASSPHRASE is an environment variable as well.
src/auth.ts
Outdated
| <username>\${env.${escapeXML(username)}}</username> | ||
| <password>\${env.${escapeXML(password)}}</password> | ||
| </server> | ||
| <server> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a user doesn't specify a GPG key, won't this be empty?
Will that cause issues for users who don't want GPG authentication
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Users will see the following by default whether they want GPG authentication or not:
<settings>
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>${env.GPG_PASSPHRASE}</passphrase>
</server>
</servers>
</settings>
And GPG_PASSPHRASE won't be provided so it will be empty string. This isn't a problem for users that don't want GPG -- maven will behave normally and will only grab information from this other server config if it needs it for the GPG plugin.
|
@clarkbw would you mind taking a look at this? |
clarkbw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn’t get a chance to test this locally but it looks pretty good.
src/auth.ts
Outdated
| if (gpgPrivateKey !== DEFAULT_GPG_PRIVATE_KEY) { | ||
| console.log('importing gpg key'); | ||
| const privateKeyDirectory: string = path.join( | ||
| os.homedir(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is the common default but in a shared runner I think we wanted to allow for paths outside the home directory such that I could drop this into a temp dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was worried about that. While the private key is being stored in a "temporary" directory inside the home directory, two setup-java actions running on a shared runner could potentially conflict.
Are you suggesting that we allow users to specify a a temporary private key directory, similar to what is already done with the settings-path option? Or would you rather see setup-java create a temporary directory using os.tmpdir() based on the repository + unique run ID without any prompting. It looks like using $GITHUB_WORKSPACE/.tmp or something is an alternative as well.
I was thinking more along the lines of the latter -- creating a known good temporary directory for the user without asking -- since a user shouldn't care about where the private key file is being written because it's being deleted.
Side note -- this comment about shared runners also brings up the potential need for a temporary key ring. After import, the GPG keyring sticks around and can be used by other runs. This wouldn't be a problem with the hosted runner because it's a new environment every time. A better approach for the shared, self-hosted runners might be to import using a temporary key ring and then clean it up in a post step.
Let me know your thoughts and I can take another crack at this 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a temporary directory, you can use RUNNER_TEMP:
The path of the temporary directory for the runner. This directory is guaranteed to be empty at the start of each job, even on self-hosted runners.
https://help.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#runner-context
Code example: https://github.com/actions/toolkit/blob/83dd3ef0f1e5bc93c5ab7072e1edf1715a01ba9d/packages/tool-cache/src/tool-cache.ts#L555
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks! I see now that installer.ts is already using this directory as well. Updated PR to use the temp directory but some more improvements can be made since installer.ts apparently already has some logic built in for fallbacks. I'll move that common temp directory logic to a separate file that both auth.ts and installer.ts use in a future commit.
The temporary key ring thing is unfortunately more complicated than I originally thought. You can't just create and use a temporary key ring without also telling the maven gpg plugin to use the same configuration.
If we want to isolate the gpg keyring for shared runners, the cleanest way I've found is to specify a new GPG home directory that lives in the temp directory. This means that each job will get its own brand new GPG configuration that is cleaned up before the next job run.
To start, we will have to import the private key via:
gpg --homedir $RUNNER_TEMP/.gnupg/ --import --batch private.asc
However, using --homedir only affects that particular import command. Future GPG commands will use the default GPG home directory which is a problem for us when it comes invoking GPG later with Maven. To fix this, we have to provide a home directory override for the GPG plugin too.
The resulting settings.xml file would then look like:
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>${env.GPG_PASSPHRASE}</passphrase>
</server>
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.homedir>${env.RUNNER_TEMP}</gpg.homedir>
</properties>
</profile>
</profiles>
</servers>Creating this default GPG home directory override in the Maven settings will break existing setup-java users that have scripted their own GPG import solution. We need to generate a different settings.xml for users that haven't specified a private key:
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
</servers>NOTE: The second gpg.passphrase server section can stay as-is without any harm but we might as well remove it if we're already conditionally generating settings.xml based on parameters.
This is going to be a bit more difficult to implement and it's already late here. I'll get cracking on this when I can.
|
Still a few kinks to work out it looks like but good progress. |
|
Looks like the homedir approach is a bust as well. Works great everywhere but Windows: Trying to start up an agent is not going well either. I'm going to keep working on this. I think it's valuable for us to clean up the keys we import so that we don't leave anything behind. We'll just have to do it a different way. Closing this out for now so that I can work on this without pinging everyone constantly. |
C:\Users\MyUser>"%ProgramFiles%\Git\usr\bin\gpg.exe" --version
gpg (GnuPG) 2.2.20-unknown
...
Home: /c/Users/MyUser/.gnupgThis seems to suggest dropping C:\Users\MyUser>tskill gpg-agent
Could not find process: gpg-agent
C:\Users\MyUser>dir c:\Users\MyUser\AppData\Local\Temp\.gnupg /b
C:\Users\MyUser>"%ProgramFiles%\Git\usr\bin\gpg.exe" --homedir "/c/Users/MyUser/AppData/Local/Temp/.gnupg" --import --batch "C:\Users\MyUser\Desktop\gpg-private.key.backup"
gpg: keybox '/c/Users/MyUser/AppData/Local/Temp/.gnupg/pubring.kbx' created
gpg: /c/Users/MyUser/AppData/Local/Temp/.gnupg/trustdb.gpg: trustdb created
gpg: key ...: public key "..." imported
gpg: key ...: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
C:\Users\MyUser>dir c:\Users\MyUser\AppData\Local\Temp\.gnupg /b
private-keys-v1.d
pubring.kbx
pubring.kbx~
trustdb.gpg
C:\Users\MyUser>tskill gpg-agent
C:\Users\MyUser> |
|
@AirQuick That's a great find. So you didn't have to start up a new GPG agent? |
|
I didn't have to. The first |
|
Also worth noting that this setup-java didn't require it because we stored ENV variables but it is possible to run a cleanup script afterward if you have keys or secrets that should be removed. Checkout this example: |
|
@clarkbw Yeah, I was thinking of that as an alternative solution since the homedir approach wasn't working very well on Windows. You could use the default homedir to import the key, parse out the key ID from the output, and then remove the key in a cleanup step. The advantage of that is that approach is that your job can take advantage of other keys that were set up prior on the shared runner. It's probably a healthier approach in the longer term. Sorry for all the back and forth on this. I use GitHub actions in a hosted-only context so learning about and wrapping my head around the shared paradigm has been a challenge. |
Adds support for GPG per #43.
I still need to demonstrate a successful test run per the contributor docs, but I figured it would be useful to get this up now.