Skip to content

Commit

Permalink
Issue 67: Adding ability to use passwords when pulling dependencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
georgit committed Dec 21, 2023
1 parent c8377b3 commit 1e1cc2a
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.sonatype.plexus.components.cipher.PlexusCipherException;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
import org.technologybrewery.habushu.exec.PoetryCommandHelper;
import org.technologybrewery.habushu.exec.PyenvCommandHelper;
import org.technologybrewery.habushu.util.MavenPasswordDecoder;

/**
* Contains logic common across the various Habushu mojos.
Expand All @@ -38,6 +42,15 @@ public abstract class AbstractHabushuMojo extends AbstractMojo {
@Parameter(defaultValue = "${settings}", readonly = true, required = true)
protected Settings settings;

/**
* Toggle for whether the server password should be decrypted or retrieved as
* plain text.
* <p>
* true (default) -> decrypt false -> plain text
*/
@Parameter(property = "habushu.decryptPassword", defaultValue = "true")
protected boolean decryptPassword;

/**
* The packaging type of the current Maven project. If it is not "habushu", then habushu packaging-related mojos
* will skip execution.
Expand Down Expand Up @@ -149,6 +162,58 @@ public abstract class AbstractHabushuMojo extends AbstractMojo {
@Parameter(defaultValue = "false", property = "habushu.rewriteLocalPathDepsInArchives")
protected boolean rewriteLocalPathDepsInArchives;

/**
* Find the username for a given server in Maven's user settings.
*
* @return the username for the server specified in Maven's settings.xml
*/
public String findUsernameForServer() {
Server server = this.settings.getServer(this.pypiRepoId);
return server != null ? server.getUsername() : null;
}

/**
* Find the password for a given server in Maven's user settings, decrypting password if needed.
*
* @return the password for the server specified in Maven's settings.xml
*/
public String findPasswordForServer() {
String password = "";
if (this.decryptPassword) {
password = decryptServerPassword();
} else {
getLog().warn(
"Detected use of plain-text password! This is a security risk! Please consider using an encrypted password!");
password = findPlaintextPasswordForServer();
}
return password;
}

/**
* Simple utility method to decrypt a stored password for a server.
*/
public String decryptServerPassword() {
String decryptedPassword = null;

try {
decryptedPassword = MavenPasswordDecoder.decryptPasswordForServer(this.settings, this.pypiRepoId);
} catch (PlexusCipherException | SecDispatcherException e) {
throw new HabushuException("Unable to decrypt stored passwords.", e);
}

return decryptedPassword;
}

/**
* Find the plain-text server password, without decryption steps, extracted from Maven's user settings.
*
* @return the password for the specified server from Maven's settings.xml
*/
public String findPlaintextPasswordForServer() {
Server server = this.settings.getServer(this.pypiRepoId);
return server != null ? server.getPassword() : null;
}

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if ("habushu".equals(packaging)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.technologybrewery.habushu.exec.PoetryCommandHelper;
import org.technologybrewery.habushu.util.HabushuUtil;

/**
* Publishes the distribution archives generated by
Expand Down Expand Up @@ -63,15 +62,6 @@ public class PublishToPyPiRepoMojo extends AbstractHabushuMojo {
@Parameter(property = "habushu.snapshotNumberDateFormatPattern")
protected String snapshotNumberDateFormatPattern;

/**
* Toggle for whether the server password should be decrypted or retrieved as
* plain text.
* <p>
* true (default) -> decrypt false -> plain text
*/
@Parameter(property = "habushu.decryptPassword", defaultValue = "true")
protected boolean decryptPassword;

/**
* Skips the entire execution of the deploy phase and does *not* publish the
* Poetry package to the configured PyPI repository. This configuration may be
Expand Down Expand Up @@ -141,14 +131,8 @@ protected void publishPackage(PoetryCommandHelper poetryHelper, boolean rebuildP
String username = null;
String password = null;
if (StringUtils.isNotEmpty(pypiRepoId)) {
username = HabushuUtil.findUsernameForServer(settings, pypiRepoId);
if (decryptPassword) {
password = HabushuUtil.decryptServerPassword(settings, pypiRepoId);
} else {
getLog().warn(
"Detected use of plain-text password! This is a security risk! Please consider using an encrypted password!");
password = HabushuUtil.findPlaintextPasswordForServer(settings, pypiRepoId);
}
username = findUsernameForServer();
password = findPasswordForServer();
}

if (StringUtils.isNotEmpty(pypiRepoUrl)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.technologybrewery.habushu.exec.PoetryCommandHelper;
import org.technologybrewery.habushu.exec.PyenvCommandHelper;
import org.technologybrewery.habushu.exec.PythonVersionHelper;
Expand Down Expand Up @@ -80,6 +79,39 @@ class PyenvAndPoetrySetup {
*/
private File patchInstallScript;

protected String username;

protected String password;

protected String pypiRepoId;

/**
* New instance - these values are typically passed in from Maven-enabled parameters in the calling Mojo.
*
* @param pythonVersion version of python to leverage
* @param usePyenv whether or not we are using pyenv to instance and activate python versions
* @param patchInstallScript patch install script path
* @param baseDir base directory from which to operate for this module
* @param rewriteLocalPathDepsInArchives see memeber variable for details
* @param username username for server
* @param password password for server
* @param pypiRepoId id of the pypi repo server
* @param log the logger to use for output
*/
public PyenvAndPoetrySetup(String pythonVersion, boolean usePyenv, File patchInstallScript,
File baseDir, boolean rewriteLocalPathDepsInArchives,
String username, String password, String pypiRepoId, Log log) {
this.pythonVersion = pythonVersion;
this.usePyenv = usePyenv;
this.patchInstallScript = patchInstallScript;
this.baseDir = baseDir;
this.rewriteLocalPathDepsInArchives = rewriteLocalPathDepsInArchives;
this.log = log;
this.username = username;
this.password = password;
this.pypiRepoId = pypiRepoId;
}

/**
* New instance - these values are typically passed in from Maven-enabled parameters in the calling Mojo.
*
Expand All @@ -98,6 +130,9 @@ public PyenvAndPoetrySetup(String pythonVersion, boolean usePyenv, File patchIns
this.baseDir = baseDir;
this.rewriteLocalPathDepsInArchives = rewriteLocalPathDepsInArchives;
this.log = log;
this.username = null;
this.password = null;
this.pypiRepoId = null;
}

public void execute() throws MojoExecutionException, MojoFailureException {
Expand Down Expand Up @@ -147,6 +182,15 @@ public void execute() throws MojoExecutionException, MojoFailureException {
log.info("Checking for updates to poetry-monorepo-dependency-plugin...");
poetryHelper.installPoetryPlugin("poetry-monorepo-dependency-plugin");
}

if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
log.info(String.format("Did not find username and password for the <server> with <id> %s. Will pull anonymously", pypiRepoId));
}
else {
log.info(String.format("Adding username and password configuration for %s", pypiRepoId));
poetryHelper.execute(
Arrays.asList("config", String.format("http-basic.%s", pypiRepoId), username, password));
}
}

private void validatePythonVersion(String currentPythonVersion) throws MojoExecutionException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,12 @@ public class ValidatePyenvAndPoetryMojo extends AbstractHabushuMojo {

@Override
public void doExecute() throws MojoExecutionException, MojoFailureException {
String username = findUsernameForServer();
String password = findPasswordForServer();

PyenvAndPoetrySetup configureTools = new PyenvAndPoetrySetup(pythonVersion, usePyenv,
patchInstallScript, getPoetryProjectBaseDir(), rewriteLocalPathDepsInArchives, getLog());
patchInstallScript, getPoetryProjectBaseDir(), rewriteLocalPathDepsInArchives,
username, password, pypiRepoId, getLog());
configureTools.execute();
}

Expand Down
Loading

0 comments on commit 1e1cc2a

Please sign in to comment.