Skip to content

Commit 899e4c9

Browse files
authored
Merge pull request #43350 from aloubyansky/3.15.0-backports1
[3.15] 3.15.0 backports
2 parents be0632c + e80c0ab commit 899e4c9

File tree

7 files changed

+96
-59
lines changed

7 files changed

+96
-59
lines changed

core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,13 @@ static void filterJarFile(Path resolvedDep, Path targetPath, Set<String> transfo
12901290
} else {
12911291
manifest = new Manifest();
12921292
}
1293-
try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(targetPath), manifest)) {
1293+
try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(targetPath))) {
1294+
JarEntry manifestEntry = new JarEntry(JarFile.MANIFEST_NAME);
1295+
// Set manifest time to epoch to always make the same jar
1296+
manifestEntry.setTime(0);
1297+
out.putNextEntry(manifestEntry);
1298+
manifest.write(out);
1299+
out.closeEntry();
12941300
Enumeration<JarEntry> entries = in.entries();
12951301
while (entries.hasMoreElements()) {
12961302
JarEntry entry = entries.nextElement();
@@ -1306,6 +1312,8 @@ static void filterJarFile(Path resolvedDep, Path targetPath, Set<String> transfo
13061312
while ((r = inStream.read(buffer)) > 0) {
13071313
out.write(buffer, 0, r);
13081314
}
1315+
} finally {
1316+
out.closeEntry();
13091317
}
13101318
} else {
13111319
log.debugf("Removed %s from %s", entryName, resolvedDep);

core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/JarResultBuildStepTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ void should_unsign_jar_when_filtered(@TempDir Path tempDir) throws Exception {
6868
}
6969
}
7070

71+
@Test
72+
void manifestTimeShouldAlwaysBeSetToEpoch(@TempDir Path tempDir) throws Exception {
73+
JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "myarchive.jar")
74+
.addClasses(Integer.class)
75+
.addManifest();
76+
Path initialJar = tempDir.resolve("initial.jar");
77+
Path filteredJar = tempDir.resolve("filtered.jar");
78+
archive.as(ZipExporter.class).exportTo(new File(initialJar.toUri()), true);
79+
JarResultBuildStep.filterJarFile(initialJar, filteredJar, Set.of("java/lang/Integer.class"));
80+
try (JarFile jarFile = new JarFile(filteredJar.toFile())) {
81+
assertThat(jarFile.stream())
82+
.filteredOn(jarEntry -> jarEntry.getName().equals(JarFile.MANIFEST_NAME))
83+
.isNotEmpty()
84+
.allMatch(jarEntry -> jarEntry.getTime() == 0);
85+
// Check that the manifest is still has attributes
86+
Manifest manifest = jarFile.getManifest();
87+
assertThat(manifest.getMainAttributes()).isNotEmpty();
88+
}
89+
}
90+
7191
private static KeyStore.PrivateKeyEntry createPrivateKeyEntry()
7292
throws NoSuchAlgorithmException, CertificateException, OperatorCreationException, CertIOException {
7393
KeyPairGenerator ky = KeyPairGenerator.getInstance("RSA");

docs/src/main/asciidoc/security-jwt.adoc

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ Create a REST endpoint in `src/main/java/org/acme/security/jwt/TokenSecuredResou
8484
----
8585
package org.acme.security.jwt;
8686
87-
import java.security.Principal;
88-
8987
import jakarta.annotation.security.PermitAll;
90-
import jakarta.enterprise.context.RequestScoped;
9188
import jakarta.inject.Inject;
9289
import jakarta.ws.rs.GET;
9390
import jakarta.ws.rs.InternalServerErrorException;
@@ -105,7 +102,7 @@ public class TokenSecuredResource {
105102
@Inject
106103
JsonWebToken jwt; // <1>
107104
108-
@GET()
105+
@GET
109106
@Path("permit-all")
110107
@PermitAll // <2>
111108
@Produces(MediaType.TEXT_PLAIN)
@@ -122,7 +119,7 @@ public class TokenSecuredResource {
122119
} else {
123120
name = ctx.getUserPrincipal().getName(); // <6>
124121
}
125-
return String.format("hello + %s,"
122+
return String.format("hello %s,"
126123
+ " isHttps: %s,"
127124
+ " authScheme: %s,"
128125
+ " hasJWT: %s",
@@ -172,7 +169,7 @@ Now that the REST endpoint is running, we can access it using a command line too
172169
[source,shell]
173170
----
174171
$ curl http://127.0.0.1:8080/secured/permit-all; echo
175-
hello + anonymous, isHttps: false, authScheme: null, hasJWT: false
172+
hello anonymous, isHttps: false, authScheme: null, hasJWT: false
176173
----
177174

178175
We have not provided any JWT in our request, so we would not expect that there is any security state seen by the endpoint,
@@ -194,7 +191,6 @@ package org.acme.security.jwt;
194191
195192
import jakarta.annotation.security.PermitAll;
196193
import jakarta.annotation.security.RolesAllowed;
197-
import jakarta.enterprise.context.RequestScoped;
198194
import jakarta.inject.Inject;
199195
import jakarta.ws.rs.GET;
200196
import jakarta.ws.rs.InternalServerErrorException;
@@ -207,7 +203,6 @@ import jakarta.ws.rs.core.SecurityContext;
207203
import org.eclipse.microprofile.jwt.JsonWebToken;
208204
209205
@Path("/secured")
210-
@RequestScoped
211206
public class TokenSecuredResource {
212207
213208
@Inject
@@ -238,7 +233,7 @@ public class TokenSecuredResource {
238233
} else {
239234
name = ctx.getUserPrincipal().getName();
240235
}
241-
return String.format("hello + %s,"
236+
return String.format("hello %s,"
242237
+ " isHttps: %s,"
243238
+ " authScheme: %s,"
244239
+ " hasJWT: %s",
@@ -455,7 +450,7 @@ curl -H "Authorization: Bearer eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUI
455450
[source,shell]
456451
----
457452
$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed; echo
458-
hello + [email protected], isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
453+
hello [email protected], isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
459454
----
460455

461456
Success! We now have:
@@ -500,14 +495,14 @@ import org.eclipse.microprofile.jwt.Claims;
500495
import org.eclipse.microprofile.jwt.JsonWebToken;
501496
502497
@Path("/secured")
503-
@RequestScoped
498+
@RequestScoped <1>
504499
public class TokenSecuredResource {
505500
506501
@Inject
507-
JsonWebToken jwt; // <1>
502+
JsonWebToken jwt; // <2>
508503
@Inject
509504
@Claim(standard = Claims.birthdate)
510-
String birthdate; // <2>
505+
String birthdate; // <3>
511506
512507
@GET
513508
@Path("permit-all")
@@ -530,7 +525,7 @@ public class TokenSecuredResource {
530525
@RolesAllowed("Admin")
531526
@Produces(MediaType.TEXT_PLAIN)
532527
public String helloRolesAllowedAdmin(@Context SecurityContext ctx) {
533-
return getResponseString(ctx) + ", birthdate: " + birthdate; // <3>
528+
return getResponseString(ctx) + ", birthdate: " + birthdate; // <4>
534529
}
535530
536531
private String getResponseString(SecurityContext ctx) {
@@ -542,7 +537,7 @@ public class TokenSecuredResource {
542537
} else {
543538
name = ctx.getUserPrincipal().getName();
544539
}
545-
return String.format("hello + %s,"
540+
return String.format("hello %s,"
546541
+ " isHttps: %s,"
547542
+ " authScheme: %s,"
548543
+ " hasJWT: %s",
@@ -554,9 +549,10 @@ public class TokenSecuredResource {
554549
}
555550
}
556551
----
557-
<1> Here we inject the JsonWebToken.
558-
<2> Here we inject the `birthday` claim as `String` - this is why the `@RequestScoped` scope is now required.
559-
<3> Here we use the injected `birthday` claim to build the final reply.
552+
<1> `RequestScoped` scope is required to support an injection of the `birthday` claim as `String`.
553+
<2> Here we inject the JsonWebToken.
554+
<3> Here we inject the `birthday` claim as `String` - this is why the `@RequestScoped` scope is now required.
555+
<4> Here we use the injected `birthday` claim to build the final reply.
560556

561557
Now generate the token again and run:
562558

@@ -568,7 +564,7 @@ curl -H "Authorization: Bearer eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUI
568564
[source,shell]
569565
----
570566
$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed-admin; echo
571-
hello + [email protected], isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
567+
hello [email protected], isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
572568
----
573569

574570
=== Package and run the application

docs/src/main/asciidoc/tls-registry-reference.adoc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The TLS Registry extension is automatically included in your project when you us
2525
As a result, applications that use the TLS Registry can be ready to handle secure communications out of the box.
2626
TLS Registry also provides features like automatic certificate reloading, Let's Encrypt (ACME) integration, Kubernetes Cert-Manager support, and compatibility with various keystore formats, such as PKCS12, PEM, and JKS.
2727

28-
[#using-the-tls-registry]
28+
[[using-the-tls-registry]]
2929
== Using the TLS registry
3030

3131
To configure a TLS connection, including key and truststores, use the `+quarkus.tls.*+` properties.
@@ -126,7 +126,7 @@ quarkus.grpc.server.plain-text=false
126126
+
127127
This configuration enables mTLS by ensuring that both the server and client validate each other's certificates, which provides an additional layer of security.
128128

129-
[#referencing-a-tls-configuration]
129+
[[referencing-a-tls-configuration]]
130130
== Referencing a TLS configuration
131131

132132
To reference an example _named_ configuration that you created by using the `quarkus.tls.<name>.*` properties as explained in <<using-the-tls-registry>>
@@ -257,7 +257,7 @@ quarkus.tls.key-store.jks.alias-password=my-alias-password
257257
* Alternatively, use SNI to select the appropriate certificate and private key.
258258
Note that all keys must use the same password.
259259

260-
[#sni]
260+
[[sni]]
261261
==== SNI
262262

263263
Server Name Indication (SNI) is a TLS extension that makes it possible for a client to specify the host name to which it attempts to connect during the TLS handshake.
@@ -585,7 +585,7 @@ When an application that uses the TLS extension starts, the TLS registry perform
585585

586586
If any of these checks fail, the application will not start.
587587

588-
[#reloading-certificates]
588+
[[reloading-certificates]]
589589
== Reloading certificates
590590

591591
The `TlsConfiguration` obtained from the `TLSConfigurationRegistry` includes a mechanism for reloading certificates.
@@ -1267,12 +1267,11 @@ quarkus.http.insecure-requests=redirect
12671267
12681268
====
12691269

1270-
[[lets-encrypt-prepare]]
1271-
12721270
The challenge is served from the primary HTTP interface (accessible from your DNS domain name).
12731271

12741272
IMPORTANT: Do not start your application yet.
12751273

1274+
[[lets-encrypt-prepare]]
12761275
=== Application preparation
12771276

12781277
Before you request a Let's Encrypt certificate:

extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,27 @@
8383
import io.smallrye.graphql.api.Entry;
8484
import io.smallrye.graphql.api.ErrorExtensionProvider;
8585
import io.smallrye.graphql.api.OneOf;
86+
import io.smallrye.graphql.api.federation.Authenticated;
8687
import io.smallrye.graphql.api.federation.ComposeDirective;
8788
import io.smallrye.graphql.api.federation.Extends;
8889
import io.smallrye.graphql.api.federation.External;
90+
import io.smallrye.graphql.api.federation.FieldSet;
8991
import io.smallrye.graphql.api.federation.Inaccessible;
9092
import io.smallrye.graphql.api.federation.InterfaceObject;
9193
import io.smallrye.graphql.api.federation.Key;
9294
import io.smallrye.graphql.api.federation.Provides;
9395
import io.smallrye.graphql.api.federation.Requires;
9496
import io.smallrye.graphql.api.federation.Shareable;
9597
import io.smallrye.graphql.api.federation.Tag;
98+
import io.smallrye.graphql.api.federation.link.Import;
99+
import io.smallrye.graphql.api.federation.link.Link;
100+
import io.smallrye.graphql.api.federation.link.Purpose;
101+
import io.smallrye.graphql.api.federation.policy.Policy;
102+
import io.smallrye.graphql.api.federation.policy.PolicyGroup;
103+
import io.smallrye.graphql.api.federation.policy.PolicyItem;
104+
import io.smallrye.graphql.api.federation.requiresscopes.RequiresScopes;
105+
import io.smallrye.graphql.api.federation.requiresscopes.ScopeGroup;
106+
import io.smallrye.graphql.api.federation.requiresscopes.ScopeItem;
96107
import io.smallrye.graphql.cdi.config.MicroProfileConfig;
97108
import io.smallrye.graphql.cdi.producer.GraphQLProducer;
98109
import io.smallrye.graphql.cdi.tracing.TracingService;
@@ -298,6 +309,17 @@ void buildFinalIndex(
298309
indexer.indexClass(io.smallrye.graphql.api.federation.Override.class);
299310
indexer.indexClass(Tag.class);
300311
indexer.indexClass(OneOf.class);
312+
indexer.indexClass(Authenticated.class);
313+
indexer.indexClass(FieldSet.class);
314+
indexer.indexClass(Link.class);
315+
indexer.indexClass(Import.class);
316+
indexer.indexClass(Purpose.class);
317+
indexer.indexClass(Policy.class);
318+
indexer.indexClass(PolicyGroup.class);
319+
indexer.indexClass(PolicyItem.class);
320+
indexer.indexClass(RequiresScopes.class);
321+
indexer.indexClass(ScopeGroup.class);
322+
indexer.indexClass(ScopeItem.class);
301323
} catch (IOException ex) {
302324
LOG.warn("Failure while creating index", ex);
303325
}

extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-server-log.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ export class QwcServerLog extends QwcAbstractLogElement {
136136
connectedCallback() {
137137
super.connectedCallback();
138138
this._toggleOnOff(true);
139+
this._history();
139140
this._loadAllLoggers();
140141
}
141142

@@ -744,4 +745,4 @@ export class QwcServerLog extends QwcAbstractLogElement {
744745

745746
}
746747

747-
customElements.define('qwc-server-log', QwcServerLog);
748+
customElements.define('qwc-server-log', QwcServerLog);

0 commit comments

Comments
 (0)