Skip to content

Commit f2b1bcf

Browse files
committed
Merge branch 'release/0.5'
2 parents d3991bd + 29761e4 commit f2b1bcf

13 files changed

Lines changed: 842 additions & 9 deletions

File tree

NOTICE

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,10 @@ This project includes:
2222
JSON-B API under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception
2323
JSON-P Default Provider under Eclipse Public License 2.0 or GNU General Public License, version 2 with the GNU Classpath Exception
2424
org.eclipse.yasson under Eclipse Public License v. 2.0 or Eclipse Distribution License v. 1.0
25+
Plexus :: Component Annotations under The Apache Software License, Version 2.0
26+
Plexus Cipher: encryption/decryption Component under Apache Public License 2.0
27+
Plexus Classworlds under The Apache Software License, Version 2.0
28+
Plexus Common Utilities under The Apache Software License, Version 2.0
29+
Plexus Security Dispatcher Component under Apache Public License 2.0
30+
Sisu-Inject-Plexus : Aggregate OSGi bundle under Eclipse Public License, Version 1.0
2531

pom.xml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<modelVersion>4.0.0</modelVersion>
77
<groupId>org.reaktivity</groupId>
88
<artifactId>rym</artifactId>
9-
<version>0.4</version>
9+
<version>0.5</version>
1010
<name>Reaktivity Management Tool</name>
1111
<description>Reaktivity Management Tool</description>
1212
<url>https://github.com/reaktivity/rym.java</url>
@@ -70,6 +70,22 @@
7070
<artifactId>ivy</artifactId>
7171
<version>2.5.0</version>
7272
</dependency>
73+
<dependency>
74+
<groupId>org.sonatype.plexus</groupId>
75+
<artifactId>plexus-sec-dispatcher</artifactId>
76+
<version>1.3</version>
77+
</dependency>
78+
<dependency>
79+
<groupId>org.sonatype.sisu</groupId>
80+
<artifactId>sisu-inject-plexus</artifactId>
81+
<version>2.3.0</version>
82+
<exclusions>
83+
<exclusion>
84+
<groupId>org.sonatype.sisu</groupId>
85+
<artifactId>sisu-inject-bean</artifactId>
86+
</exclusion>
87+
</exclusions>
88+
</dependency>
7389
<dependency>
7490
<groupId>org.junit.jupiter</groupId>
7591
<artifactId>junit-jupiter-engine</artifactId>

src/main/java/org/reaktivity/rym/internal/RymCli.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.reaktivity.rym.internal;
1717

1818
import org.reaktivity.rym.internal.commands.clean.RymClean;
19+
import org.reaktivity.rym.internal.commands.encrypt.RymEncrypt;
1920
import org.reaktivity.rym.internal.commands.install.RymInstall;
2021
import org.reaktivity.rym.internal.commands.wrap.RymWrap;
2122

@@ -30,7 +31,8 @@
3031
Help.class,
3132
RymWrap.class,
3233
RymInstall.class,
33-
RymClean.class
34+
RymClean.class,
35+
RymEncrypt.class
3436
})
3537
public final class RymCli
3638
{

src/main/java/org/reaktivity/rym/internal/RymCommand.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ public abstract class RymCommand implements Runnable
3636
hidden = true)
3737
public Boolean silent = false;
3838

39+
@Option(name = { "--settings-directory" },
40+
description = "settings directory",
41+
typeConverterProvider = RymPathConverterProvider.class)
42+
public Path settingsDir = Paths.get(System.getProperty("user.home"), ".rym");
43+
3944
@Option(name = { "--config-directory" },
4045
description = "config directory",
4146
typeConverterProvider = RymPathConverterProvider.class)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/**
2+
* Copyright 2016-2021 The Reaktivity Project
3+
*
4+
* The Reaktivity Project licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
package org.reaktivity.rym.internal.commands.encrypt;
17+
18+
import static java.nio.file.Files.createDirectories;
19+
import static java.nio.file.Files.newInputStream;
20+
import static java.nio.file.Files.newOutputStream;
21+
import static org.reaktivity.rym.internal.settings.RymSecrets.decryptSecret;
22+
import static org.reaktivity.rym.internal.settings.RymSecrets.encryptSecret;
23+
import static org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION;
24+
25+
import java.io.IOException;
26+
import java.io.InputStream;
27+
import java.io.OutputStream;
28+
import java.nio.file.Files;
29+
import java.nio.file.Path;
30+
import java.security.SecureRandom;
31+
import java.util.Random;
32+
import java.util.Scanner;
33+
34+
import javax.json.bind.Jsonb;
35+
import javax.json.bind.JsonbBuilder;
36+
import javax.json.bind.JsonbConfig;
37+
38+
import org.reaktivity.rym.internal.RymCommand;
39+
import org.reaktivity.rym.internal.settings.RymSecurity;
40+
import org.sonatype.plexus.components.cipher.PlexusCipherException;
41+
42+
import com.github.rvesse.airline.annotations.Command;
43+
44+
@Command(
45+
name = "encrypt",
46+
description = "Encrypt passwords")
47+
public class RymEncrypt extends RymCommand
48+
{
49+
private static final String SECRET_CHARS =
50+
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/";
51+
52+
@Override
53+
public void invoke()
54+
{
55+
try
56+
{
57+
RymSecurity security = readSecurity(settingsDir);
58+
59+
if (security.secret == null)
60+
{
61+
final String secret = generateSecret(32);
62+
security.secret = encryptSecret(secret, SYSTEM_PROPERTY_SEC_LOCATION);
63+
writeSecurity(security);
64+
}
65+
66+
assert security.secret != null;
67+
68+
final String secret = decryptSecret(security.secret, SYSTEM_PROPERTY_SEC_LOCATION);
69+
try (Scanner scanner = new Scanner(System.in))
70+
{
71+
String password = scanner.nextLine().trim();
72+
String encrypted = encryptSecret(password, secret);
73+
74+
System.out.println(encrypted);
75+
}
76+
}
77+
catch (Exception ex)
78+
{
79+
throw new RuntimeException(ex);
80+
}
81+
}
82+
83+
private RymSecurity readSecurity(
84+
Path settingsDir) throws IOException, PlexusCipherException
85+
{
86+
Path securityFile = settingsDir.resolve("security.json");
87+
88+
RymSecurity security = new RymSecurity();
89+
90+
Jsonb builder = JsonbBuilder.newBuilder()
91+
.withConfig(new JsonbConfig().withFormatting(true))
92+
.build();
93+
94+
if (Files.exists(securityFile))
95+
{
96+
try (InputStream in = newInputStream(securityFile))
97+
{
98+
security = builder.fromJson(in, RymSecurity.class);
99+
}
100+
}
101+
102+
return security;
103+
}
104+
105+
private void writeSecurity(
106+
RymSecurity security) throws IOException
107+
{
108+
Path securityFile = settingsDir.resolve("security.json");
109+
110+
Jsonb builder = JsonbBuilder.newBuilder()
111+
.withConfig(new JsonbConfig().withFormatting(true))
112+
.build();
113+
114+
createDirectories(settingsDir);
115+
try (OutputStream out = newOutputStream(securityFile))
116+
{
117+
builder.toJson(security, out);
118+
}
119+
}
120+
121+
private String generateSecret(
122+
int length) throws PlexusCipherException
123+
{
124+
Random random = new SecureRandom();
125+
char[] secret = new char[length];
126+
127+
for (int i = 0; i < secret.length; i++)
128+
{
129+
int charIndex = random.nextInt(SECRET_CHARS.length());
130+
secret[i] = SECRET_CHARS.charAt(charIndex);
131+
}
132+
133+
return new String(secret);
134+
}
135+
}

src/main/java/org/reaktivity/rym/internal/commands/install/RymInstall.java

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
import static java.nio.file.Files.newOutputStream;
2323
import static java.util.Collections.emptyList;
2424
import static java.util.Collections.list;
25+
import static java.util.Collections.singletonMap;
2526
import static java.util.Comparator.reverseOrder;
2627
import static java.util.Optional.ofNullable;
2728
import static java.util.stream.Collectors.toList;
2829
import static java.util.stream.Collectors.toMap;
30+
import static org.reaktivity.rym.internal.settings.RymSecrets.decryptSecret;
31+
import static org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION;
2932

3033
import java.io.File;
3134
import java.io.IOException;
@@ -69,11 +72,17 @@
6972
import org.apache.ivy.util.DefaultMessageLogger;
7073
import org.apache.ivy.util.Message;
7174
import org.apache.ivy.util.MessageLogger;
75+
import org.apache.ivy.util.url.CredentialsStore;
7276
import org.reaktivity.rym.internal.RymCommand;
7377
import org.reaktivity.rym.internal.commands.install.cache.RymArtifact;
7478
import org.reaktivity.rym.internal.commands.install.cache.RymArtifactId;
7579
import org.reaktivity.rym.internal.commands.install.cache.RymCache;
7680
import org.reaktivity.rym.internal.commands.install.cache.RymModule;
81+
import org.reaktivity.rym.internal.settings.RymCredentials;
82+
import org.reaktivity.rym.internal.settings.RymSecrets;
83+
import org.reaktivity.rym.internal.settings.RymSecurity;
84+
import org.reaktivity.rym.internal.settings.RymSettings;
85+
import org.sonatype.plexus.components.cipher.PlexusCipherException;
7786

7887
import com.github.rvesse.airline.annotations.Command;
7988
import com.github.rvesse.airline.annotations.Option;
@@ -86,12 +95,11 @@ public final class RymInstall extends RymCommand
8695
private static final String MODULE_INFO_JAVA_FILENAME = "module-info.java";
8796
private static final String MODULE_INFO_CLASS_FILENAME = "module-info.class";
8897

98+
private static final Map<String, String> DEFAULT_REALMS = initDefaultRealms();
99+
89100
@Option(name = { "--debug" })
90101
public Boolean debug = false;
91102

92-
@Option(name = { "--ignore-signing-information" })
93-
public Boolean ignoreSigning = false;
94-
95103
@Option(name = { "--exclude-local-repository" })
96104
public boolean excludeLocalRepo;
97105

@@ -116,6 +124,7 @@ public void invoke()
116124
config = overrideConfigIfLocked(config, rymFile, lockFile);
117125

118126
logger.info("resolving dependencies");
127+
readSettings(settingsDir);
119128
createDirectories(cacheDir);
120129
List<RymRepository> repositories = new ArrayList<>(config.repositories);
121130
if (!excludeLocalRepo)
@@ -182,6 +191,58 @@ public void invoke()
182191
}
183192
}
184193

194+
private void readSettings(
195+
Path settingsDir) throws IOException, PlexusCipherException
196+
{
197+
Path settingsFile = settingsDir.resolve("settings.json");
198+
199+
RymSettings settings = new RymSettings();
200+
settings.credentials = emptyList();
201+
202+
Jsonb builder = JsonbBuilder.newBuilder()
203+
.withConfig(new JsonbConfig().withFormatting(true))
204+
.build();
205+
206+
if (Files.exists(settingsFile))
207+
{
208+
try (InputStream in = newInputStream(settingsFile))
209+
{
210+
settings = builder.fromJson(in, RymSettings.class);
211+
}
212+
}
213+
214+
if (settings.credentials.size() > 0)
215+
{
216+
Path securityFile = settingsDir.resolve("security.json");
217+
218+
RymSecurity security = new RymSecurity();
219+
220+
if (Files.exists(securityFile))
221+
{
222+
try (InputStream in = newInputStream(securityFile))
223+
{
224+
security = builder.fromJson(in, RymSecurity.class);
225+
}
226+
}
227+
228+
security.secret = decryptSecret(security.secret, SYSTEM_PROPERTY_SEC_LOCATION);
229+
230+
for (RymCredentials credentials : settings.credentials)
231+
{
232+
String realm = defaultRealmIfNecessary(credentials);
233+
String host = credentials.host;
234+
String username = credentials.username;
235+
String password = RymSecrets.decryptSecret(credentials.password, security.secret);
236+
237+
CredentialsStore.INSTANCE.addCredentials(
238+
realm,
239+
host,
240+
username,
241+
password);
242+
}
243+
}
244+
}
245+
185246
private RymConfiguration readOrDefaultConfig(
186247
Path rymFile) throws IOException
187248
{
@@ -573,10 +634,7 @@ private void linkModules(
573634
"--compress", "2",
574635
"--add-modules", moduleNames.collect(Collectors.joining(","))));
575636

576-
if (ignoreSigning)
577-
{
578-
args.add("--ignore-signing-information");
579-
}
637+
args.add("--ignore-signing-information");
580638

581639
if (!debug)
582640
{
@@ -696,4 +754,16 @@ private void deleteDirectories(
696754
.forEach(File::delete);
697755
}
698756
}
757+
758+
private String defaultRealmIfNecessary(
759+
RymCredentials credentials)
760+
{
761+
return ofNullable(credentials.realm)
762+
.orElse(DEFAULT_REALMS.get(credentials.host));
763+
}
764+
765+
private static Map<String, String> initDefaultRealms()
766+
{
767+
return singletonMap("maven.pkg.github.com", "GitHub Package Registry");
768+
}
699769
}

0 commit comments

Comments
 (0)