Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
import org.apache.activemq.artemis.nativo.jlibaio.LibaioFile;
import org.apache.activemq.artemis.utils.FileUtil;
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

Expand Down Expand Up @@ -444,10 +445,24 @@ private String getClusterUser() {
return clusterUser;
}

private String getClusterPassword() {
protected void setClusterPassword(String clusterPassword) {
this.clusterPassword = clusterPassword;
}

protected String getClusterPassword() {
if (clusterPassword == null) {
clusterPassword = inputPassword("--cluster-password", "What is the cluster password?", "password-admin");
}
if (!PasswordMaskingUtil.isEncMasked(clusterPassword)) {
try {
clusterPassword = PasswordMaskingUtil.wrap(PasswordMaskingUtil.getDefaultCodec().encode(clusterPassword));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@jbertram I don't understand this.. you're only masking the password if sent through the input..

I think if you did ./artemis create --cluster --password myPassowrd

it should also be masked, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

as a matter of fact there are a few smoke tests (e.g. ClsuteredLargeMessageTest) that will use the clustered CLI, and it would be a good test basis.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good idea. Fixed.

getActionContext().out.println("Using masked cluster-password: " + clusterPassword);
} catch (Exception e) {
getActionContext().err.println("Warning: Failed to mask password.");
getActionContext().err.println("Reason: " + e.getMessage());
e.printStackTrace();
}
}
return clusterPassword;
}

Expand Down Expand Up @@ -489,7 +504,9 @@ public String getPassword() {
password = inputPassword("--password", "What is the default password?", "admin");
}

password = HashUtil.tryHash(getActionContext(), password);
if (!PasswordMaskingUtil.isEncMasked(password)) {
password = HashUtil.tryHash(getActionContext(), password);
}

return password;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ public class InputAbstract extends ActionAbstract {
private static boolean inputEnabled = false;

/**
* Test cases validating or using the CLI cannot deal with inputs, so they are generally disabled, however the main
* method from the CLI will enable it back.
* Test cases validating or using the CLI usually don't deal with inputs, so they are generally disabled, however
* the main method from the CLI will enable it back.
*/
public static void enableInput() {
inputEnabled = true;
}

public static void disableInput() {
inputEnabled = false;
}

@Option(names = "--silent", description = "Disable all the inputs, and make a best guess for any required input.")
private boolean silentInput = false;

Expand Down Expand Up @@ -145,4 +149,8 @@ public Object execute(ActionContext context) throws Exception {

return null;
}

public void setLineReader(InputReader lineReader) {
this.lineReader = lineReader;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;

import org.apache.activemq.artemis.cli.commands.util.input.InputReader;
import org.apache.activemq.artemis.tests.extensions.TargetTempDirFactory;
import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.SensitiveDataCodec;
import org.apache.activemq.cli.test.TestActionContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -84,4 +91,98 @@ private boolean fileContains(File file, String search) {
}
return false;
}

@Test
public void testMaskClusterPasswordUserInput() throws Exception {
final String password = RandomUtil.randomUUIDString();

Create c = new Create();
Create.enableInput();
try {
InputReader inputReader = Mockito.mock(InputReader.class);
Mockito.when(inputReader.readPassword(Mockito.anyString())).thenReturn(password);
c.setLineReader(inputReader);

assertEquals(PasswordMaskingUtil.wrap(PasswordMaskingUtil.getDefaultCodec().encode(password)), c.getClusterPassword());
} finally {
Create.disableInput();
}
}

@Test
public void testMaskClusterPasswordSwitch() throws Exception {
final String password = RandomUtil.randomUUIDString();

Create c = new Create();
c.setClusterPassword(password);
assertEquals(PasswordMaskingUtil.wrap(PasswordMaskingUtil.getDefaultCodec().encode(password)), c.getClusterPassword());
}

@Test
public void testMaskClusterPasswordAlreadyEncoded() throws Exception {
final String password = RandomUtil.randomUUIDString();
final String encodedPassword = PasswordMaskingUtil.wrap(PasswordMaskingUtil.getDefaultCodec().encode(password));

Create c = new Create();
c.setClusterPassword(encodedPassword);
assertEquals(encodedPassword, c.getClusterPassword());
}

@Test
public void testMaskClusterPasswordMultipleGets() throws Exception {
final String password = RandomUtil.randomUUIDString();
final String encodedPassword = PasswordMaskingUtil.wrap(PasswordMaskingUtil.getDefaultCodec().encode(password));

Create c = new Create();
c.setClusterPassword(password);
assertEquals(encodedPassword, c.getClusterPassword());
assertEquals(encodedPassword, c.getClusterPassword());
}

@Test
public void testMaskAdminPasswordUserInput() throws Exception {
final String password = RandomUtil.randomUUIDString();

Create c = new Create();
Create.enableInput();
try {
InputReader inputReader = Mockito.mock(InputReader.class);
Mockito.when(inputReader.readPassword(Mockito.anyString())).thenReturn(password);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you should also test when through arguments.. (non masked)..

so it doesn't matter to use the input here.. you could just always mask.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

c.setLineReader(inputReader);

assertTrue(PasswordMaskingUtil.getDefaultCodec(Map.of(DefaultSensitiveStringCodec.ALGORITHM, DefaultSensitiveStringCodec.ONE_WAY)).verify(password.toCharArray(), PasswordMaskingUtil.unwrap(c.getPassword())));
} finally {
Create.disableInput();
}
}

@Test
public void testMaskAdminPasswordSwitch() throws Exception {
final String password = RandomUtil.randomUUIDString();

Create c = new Create();
c.setPassword(password);
assertTrue(PasswordMaskingUtil.getDefaultCodec(Map.of(DefaultSensitiveStringCodec.ALGORITHM, DefaultSensitiveStringCodec.ONE_WAY)).verify(password.toCharArray(), PasswordMaskingUtil.unwrap(c.getPassword())));
}

@Test
public void testMaskAdminPasswordAlreadyHashed() throws Exception {
final String password = RandomUtil.randomUUIDString();
final String hashedPassword = PasswordMaskingUtil.getHashProcessor().hash(password);

Create c = new Create();
c.setPassword(hashedPassword);
assertEquals(hashedPassword, c.getPassword());
}

@Test
public void testMaskAdminPasswordMultipleGets() throws Exception {
final String password = RandomUtil.randomUUIDString();
final SensitiveDataCodec<String> codec = PasswordMaskingUtil.getDefaultCodec(Map.of(DefaultSensitiveStringCodec.ALGORITHM, DefaultSensitiveStringCodec.ONE_WAY));

Create c = new Create();
c.setPassword(password);
assertTrue(codec.verify(password.toCharArray(), PasswordMaskingUtil.unwrap(c.getPassword())));
assertTrue(codec.verify(password.toCharArray(), PasswordMaskingUtil.unwrap(c.getPassword())));
}
}