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

[MNG-8285] Implement mvnenc CLI tool #1793

Merged
merged 27 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b2bded8
Mvnenc
cstamas Oct 10, 2024
80304fc
Merge remote-tracking branch 'origin/master' into mvnenc
cstamas Oct 10, 2024
2bdb4bd
More WIP
cstamas Oct 10, 2024
2010d52
WIP
cstamas Oct 10, 2024
6ae219e
Add logging
cstamas Oct 10, 2024
5575195
Reformat
cstamas Oct 10, 2024
6682949
Moved pinetry to sec dispatcher
cstamas Oct 10, 2024
db1f5ff
Adopt latest sec-dispatcher changes
cstamas Oct 11, 2024
8cc2a01
Move the component to final place and make it deprecated
cstamas Oct 11, 2024
9c79881
Tune wizard a bit
cstamas Oct 11, 2024
ee9e060
Allow editing of template values (those having $ in them)
cstamas Oct 11, 2024
f776207
Alter filename to not overwrite any existing file
cstamas Oct 11, 2024
685957d
Drop unused options
cstamas Oct 11, 2024
f1a2e43
Multiple things:
cstamas Oct 11, 2024
0711d39
Tidy up and start "migrate" goal for mvnenc
cstamas Oct 11, 2024
2619afc
Merge remote-tracking branch 'origin/master' into mvnenc
cstamas Oct 12, 2024
7d6d2e6
Adopt latest sec dispatcher changes
cstamas Oct 12, 2024
ec45cde
Drop the migrate goal
cstamas Oct 12, 2024
a4059ab
Allow "legacy only" mode
cstamas Oct 12, 2024
6b9b233
Use released sec-dispatcher
cstamas Oct 14, 2024
d967290
Lower to warn for now
cstamas Oct 14, 2024
db00ad1
Return error log level, but decrypt only when
cstamas Oct 14, 2024
31c3380
Use new API
cstamas Oct 14, 2024
a57f632
Decrypt can now detect bad input
cstamas Oct 14, 2024
46e2632
Merge remote-tracking branch 'upstream/master' into mvnenc
cstamas Oct 14, 2024
1c4015e
Update to 4.0.1
cstamas Oct 14, 2024
ad936b3
Remove dupe line
cstamas Oct 14, 2024
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
1 change: 1 addition & 0 deletions apache-maven/src/assembly/component.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ under the License.
<include>mvn</include>
<include>mvnenc</include>
<include>mvnDebug</include>
<include>mvnencDebug</include>
<!-- This is so that CI systems can periodically run the profiler -->
<include>mvnyjp</include>
</includes>
Expand Down
35 changes: 35 additions & 0 deletions apache-maven/src/assembly/maven/bin/mvnencDebug
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/sh

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# -----------------------------------------------------------------------------
# Apache Maven Debug Script
#
# Environment Variable Prerequisites
#
# JAVA_HOME (Optional) Points to a Java installation.
# MAVEN_OPTS (Optional) Java runtime options used when Maven is executed.
# MAVEN_SKIP_RC (Optional) Flag to disable loading of mavenrc files.
# MAVEN_DEBUG_ADDRESS (Optional) Set the debug address. Default value is localhost:8000
# -----------------------------------------------------------------------------

MAVEN_DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=${MAVEN_DEBUG_ADDRESS:-localhost:8000}"

echo Preparing to execute Maven in debug mode

env MAVEN_OPTS="$MAVEN_OPTS" MAVEN_DEBUG_OPTS="$MAVEN_DEBUG_OPTS" "`dirname "$0"`/mvnenc" "$@"
44 changes: 44 additions & 0 deletions apache-maven/src/assembly/maven/bin/mvnencDebug.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.

@REM -----------------------------------------------------------------------------
@REM Apache Maven Debug Script
@REM
@REM Environment Variable Prerequisites
@REM
@REM JAVA_HOME (Optional) Points to a Java installation.
@REM MAVEN_BATCH_ECHO (Optional) Set to 'on' to enable the echoing of the batch commands.
@REM MAVEN_BATCH_PAUSE (Optional) set to 'on' to wait for a key stroke before ending.
@REM MAVEN_OPTS (Optional) Java runtime options used when Maven is executed.
@REM MAVEN_SKIP_RC (Optional) Flag to disable loading of mavenrc files.
@REM MAVEN_DEBUG_ADDRESS (Optional) Set the debug address. Default value is localhost:8000
@REM -----------------------------------------------------------------------------

@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%"=="on" echo %MAVEN_BATCH_ECHO%

@setlocal

if "%MAVEN_DEBUG_ADDRESS%"=="" @set MAVEN_DEBUG_ADDRESS=localhost:8000

@set MAVEN_DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%MAVEN_DEBUG_ADDRESS%

@call "%~dp0"mvnenc.cmd %*
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,18 @@
@Experimental
public interface EncryptOptions extends Options {
/**
* Returns the cipher that the user wants to use for non-dispatched encryption.
* Should the operation be forced (ie overwrite existing config, if any).
*
* @return an {@link Optional} containing the cipher string, or empty if not specified
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
*/
@Nonnull
Optional<String> cipher();
Optional<Boolean> force();

/**
* Returns the master source that the user wants to use for non-dispatched encryption.
* Should imply "yes" to all questions.
*
* @return an {@link Optional} containing the master source string, or empty if not specified
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
*/
@Nonnull
Optional<String> masterSource();

/**
* Returns the dispatcher to use for dispatched encryption.
*
* @return an {@link Optional} containing the dispatcher string, or empty if not specified
*/
@Nonnull
Optional<String> dispatcher();
Optional<Boolean> yes();

/**
* Returns the list of encryption goals to be executed.
Expand Down
4 changes: 4 additions & 0 deletions maven-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ under the License.

<build>
<plugins>
<plugin>
<groupId>org.eclipse.sisu</groupId>
<artifactId>sisu-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
Expand Down
11 changes: 2 additions & 9 deletions maven-cli/src/main/java/org/apache/maven/cling/ClingSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.apache.maven.api.cli.InvokerRequest;
import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.ParserException;
import org.apache.maven.jline.MessageUtils;
import org.codehaus.plexus.classworlds.ClassWorld;

import static java.util.Objects.requireNonNull;
Expand Down Expand Up @@ -65,8 +64,6 @@ private ClingSupport(ClassWorld classWorld, boolean classWorldManaged) {
* The main entry point.
*/
public int run(String[] args) throws IOException {
MessageUtils.systemInstall();
MessageUtils.registerShutdownHook();
try (Invoker<R> invoker = createInvoker()) {
return invoker.invoke(parseArguments(args));
} catch (ParserException e) {
Expand All @@ -75,12 +72,8 @@ public int run(String[] args) throws IOException {
} catch (InvokerException e) {
return 1;
} finally {
try {
if (classWorldManaged) {
classWorld.close();
}
} finally {
MessageUtils.systemUninstall();
if (classWorldManaged) {
classWorld.close();
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.maven.cling.invoker.mvn.DefaultMavenParser;
import org.apache.maven.cling.invoker.mvn.local.DefaultLocalMavenInvoker;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.apache.maven.jline.MessageUtils;
import org.codehaus.plexus.classworlds.ClassWorld;

/**
Expand Down Expand Up @@ -59,6 +60,17 @@ public MavenCling(ClassWorld classWorld) {
super(classWorld);
}

@Override
public int run(String[] args) throws IOException {
MessageUtils.systemInstall();
MessageUtils.registerShutdownHook();
try {
return super.run(args);
} finally {
MessageUtils.systemUninstall();
}
}

@Override
protected Invoker<MavenInvokerRequest<MavenOptions>> createInvoker() {
return new DefaultLocalMavenInvoker(
Expand Down
23 changes: 21 additions & 2 deletions maven-cli/src/main/java/org/apache/maven/cling/MavenEncCling.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker;
import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptParser;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.apache.maven.jline.MessageUtils;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

/**
* Maven encrypt CLI "new-gen".
Expand All @@ -52,6 +55,8 @@ public static int main(String[] args, ClassWorld world) throws IOException {
return new MavenEncCling(world).run(args);
}

private Terminal terminal;

public MavenEncCling() {
super();
}
Expand All @@ -60,10 +65,24 @@ public MavenEncCling(ClassWorld classWorld) {
super(classWorld);
}

@Override
public int run(String[] args) throws IOException {
terminal = TerminalBuilder.builder().build();
MessageUtils.systemInstall(terminal);
MessageUtils.registerShutdownHook();
try {
return super.run(args);
} finally {
MessageUtils.systemUninstall();
}
}

@Override
protected Invoker<EncryptInvokerRequest> createInvoker() {
return new DefaultEncryptInvoker(
ProtoLookup.builder().addMapping(ClassWorld.class, classWorld).build());
return new DefaultEncryptInvoker(ProtoLookup.builder()
.addMapping(ClassWorld.class, classWorld)
.addMapping(Terminal.class, terminal)
.build());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,17 @@ private static CommonsCliEncryptOptions interpolate(
}

@Override
public Optional<String> cipher() {
if (commandLine.hasOption(CLIManager.CIPHER)) {
return Optional.of(commandLine.getOptionValue(CLIManager.CIPHER));
public Optional<Boolean> force() {
if (commandLine.hasOption(CLIManager.FORCE)) {
return Optional.of(Boolean.TRUE);
}
return Optional.empty();
}

@Override
public Optional<String> masterSource() {
if (commandLine.hasOption(CLIManager.MASTER_SOURCE)) {
return Optional.of(commandLine.getOptionValue(CLIManager.MASTER_SOURCE));
}
return Optional.empty();
}

@Override
public Optional<String> dispatcher() {
if (commandLine.hasOption(CLIManager.DISPATCHER)) {
return Optional.of(commandLine.getOptionValue(CLIManager.DISPATCHER));
public Optional<Boolean> yes() {
if (commandLine.hasOption(CLIManager.YES)) {
return Optional.of(Boolean.TRUE);
}
return Optional.empty();
}
Expand All @@ -109,24 +101,19 @@ public EncryptOptions interpolate(Collection<Map<String, String>> properties) {
}

protected static class CLIManager extends CommonsCliOptions.CLIManager {
public static final String CIPHER = "c";
public static final String MASTER_SOURCE = "m";
public static final String DISPATCHER = "d";
public static final String FORCE = "f";
public static final String YES = "y";

@Override
protected void prepareOptions(org.apache.commons.cli.Options options) {
super.prepareOptions(options);
options.addOption(Option.builder(CIPHER)
.longOpt("cipher")
.desc("The cipher that user wants to use for non-dispatched encryption")
.build());
options.addOption(Option.builder(MASTER_SOURCE)
.longOpt("master-source")
.desc("The master source that user wants to use for non-dispatched encryption")
options.addOption(Option.builder(FORCE)
.longOpt("force")
.desc("Should overwrite without asking any configuration?")
.build());
options.addOption(Option.builder(DISPATCHER)
.longOpt("dispatcher")
.desc("The dispatcher to use for dispatched encryption")
options.addOption(Option.builder(YES)
.longOpt("yes")
.desc("Should imply user answered \"yes\" to all incoming questions?")
.build());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.cling.invoker.mvnenc;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.maven.api.services.Prompter;
import org.apache.maven.api.services.PrompterException;
import org.codehaus.plexus.components.secdispatcher.MasterSource;
import org.codehaus.plexus.components.secdispatcher.MasterSourceMeta;
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;

/**
* Trivial master password source using Maven {@link Prompter} service.
*/
@Singleton
@Named(ConsolePasswordPrompt.NAME)
public class ConsolePasswordPrompt implements MasterSource, MasterSourceMeta {
public static final String NAME = "console-prompt";

private final Prompter prompter;

@Inject
public ConsolePasswordPrompt(Prompter prompter) {
this.prompter = prompter;
}

@Override
public String description() {
return "Secure console password prompt";
}

@Override
public Optional<String> configTemplate() {
return Optional.empty();
}

@Override
public String handle(String config) throws SecDispatcherException {
if (NAME.equals(config)) {
try {
return prompter.promptForPassword("Enter the master password: ");
} catch (PrompterException e) {
throw new SecDispatcherException("Could not collect the password", e);
}
}
return null;
}

@Override
public SecDispatcher.ValidationResponse validateConfiguration(String config) {
if (NAME.equals(config)) {
return new SecDispatcher.ValidationResponse(getClass().getSimpleName(), true, Map.of(), List.of());
}
return null;
}
}
Loading