22
33import static com .example .security .Security .ThreadInfo .newBuilder ;
44import static io .quarkus .grpc .auth .BlockingHttpSecurityPolicy .BLOCK_REQUEST ;
5+ import static io .quarkus .security .spi .runtime .AuthorizationSuccessEvent .AUTHORIZATION_CONTEXT ;
56import static org .assertj .core .api .Assertions .assertThat ;
67import static org .awaitility .Awaitility .await ;
8+ import static org .junit .jupiter .api .Assertions .assertEquals ;
9+ import static org .junit .jupiter .api .Assertions .assertFalse ;
10+ import static org .junit .jupiter .api .Assertions .assertInstanceOf ;
11+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
12+ import static org .junit .jupiter .api .Assertions .assertTrue ;
713
814import java .util .List ;
915import java .util .concurrent .CopyOnWriteArrayList ;
1218import java .util .concurrent .atomic .AtomicReference ;
1319
1420import jakarta .annotation .security .RolesAllowed ;
21+ import jakarta .inject .Inject ;
1522
1623import org .jboss .shrinkwrap .api .ShrinkWrap ;
1724import org .jboss .shrinkwrap .api .asset .StringAsset ;
1825import org .jboss .shrinkwrap .api .spec .JavaArchive ;
1926import org .junit .jupiter .api .Assertions ;
27+ import org .junit .jupiter .api .BeforeEach ;
2028import org .junit .jupiter .api .Test ;
2129
2230import com .example .security .SecuredService ;
2634import io .quarkus .grpc .GrpcClient ;
2735import io .quarkus .grpc .GrpcClientUtils ;
2836import io .quarkus .grpc .GrpcService ;
37+ import io .quarkus .security .UnauthorizedException ;
38+ import io .quarkus .security .runtime .interceptor .check .RolesAllowedCheck ;
39+ import io .quarkus .security .spi .runtime .AuthenticationSuccessEvent ;
40+ import io .quarkus .security .spi .runtime .AuthorizationFailureEvent ;
41+ import io .quarkus .security .spi .runtime .AuthorizationSuccessEvent ;
2942import io .quarkus .test .QuarkusUnitTest ;
3043import io .smallrye .common .annotation .Blocking ;
3144import io .smallrye .mutiny .Multi ;
@@ -54,7 +67,7 @@ protected static QuarkusUnitTest createQuarkusUnitTest(String extraProperty, boo
5467 props += extraProperty ;
5568 }
5669 var jar = ShrinkWrap .create (JavaArchive .class )
57- .addClasses (Service .class , BlockingHttpSecurityPolicy .class )
70+ .addClasses (Service .class , BlockingHttpSecurityPolicy .class , SecurityEventObserver . class )
5871 .addPackage (SecuredService .class .getPackage ())
5972 .add (new StringAsset (props ), "application.properties" );
6073 return useGrpcAuthMechanism ? jar .addClass (BasicGrpcSecurityMechanism .class ) : jar ;
@@ -67,6 +80,14 @@ protected static QuarkusUnitTest createQuarkusUnitTest(String extraProperty, boo
6780 @ GrpcClient
6881 SecuredService securityClient ;
6982
83+ @ Inject
84+ SecurityEventObserver securityEventObserver ;
85+
86+ @ BeforeEach
87+ void clearEvents () {
88+ securityEventObserver .getStorage ().clear ();
89+ }
90+
7091 @ Test
7192 void shouldSecureUniEndpoint () {
7293 Metadata headers = new Metadata ();
@@ -83,6 +104,7 @@ void shouldSecureUniEndpoint() {
83104
84105 await ().atMost (10 , TimeUnit .SECONDS )
85106 .until (() -> resultCount .get () == 1 );
107+ assertSecurityEventsFired ("john" );
86108 }
87109
88110 @ Test
@@ -101,6 +123,7 @@ void shouldSecureBlockingUniEndpoint() {
101123
102124 await ().atMost (10 , TimeUnit .SECONDS )
103125 .until (() -> resultCount .get () == 1 );
126+ assertSecurityEventsFired ("john" );
104127 }
105128
106129 @ Test
@@ -117,6 +140,7 @@ void shouldSecureMultiEndpoint() {
117140 .until (() -> results .size () == 5 );
118141
119142 assertThat (results .stream ().filter (e -> !e )).isEmpty ();
143+ assertSecurityEventsFired ("paul" );
120144 }
121145
122146 @ Test
@@ -133,6 +157,7 @@ void shouldSecureBlockingMultiEndpoint() {
133157 .until (() -> results .size () == 5 );
134158
135159 assertThat (results .stream ().filter (e -> e )).isEmpty ();
160+ assertSecurityEventsFired ("paul" );
136161 }
137162
138163 @ Test
@@ -167,6 +192,16 @@ void shouldFailWithInvalidInsufficientRole() {
167192
168193 await ().atMost (10 , TimeUnit .SECONDS )
169194 .until (() -> error .get () != null );
195+
196+ // we don't check exact count as HTTP Security policies are not supported when gRPC is running on separate server
197+ assertFalse (securityEventObserver .getStorage ().isEmpty ());
198+ // fails RolesAllowed check as the anonymous identity has no roles
199+ AuthorizationFailureEvent event = (AuthorizationFailureEvent ) securityEventObserver
200+ .getStorage ().get (securityEventObserver .getStorage ().size () - 1 );
201+ assertNotNull (event .getSecurityIdentity ());
202+ assertTrue (event .getSecurityIdentity ().isAnonymous ());
203+ assertInstanceOf (UnauthorizedException .class , event .getAuthorizationFailure ());
204+ assertEquals (RolesAllowedCheck .class .getName (), event .getAuthorizationContext ());
170205 }
171206
172207 @ Test
@@ -186,6 +221,7 @@ void shouldSecureUniEndpointWithBlockingHttpSecurityPolicy() {
186221
187222 await ().atMost (10 , TimeUnit .SECONDS )
188223 .until (() -> resultCount .get () == 1 );
224+ assertSecurityEventsFired ("john" );
189225 }
190226
191227 @ Test
@@ -205,6 +241,7 @@ void shouldSecureBlockingUniEndpointWithBlockingHttpSecurityPolicy() {
205241
206242 await ().atMost (10 , TimeUnit .SECONDS )
207243 .until (() -> resultCount .get () == 1 );
244+ assertSecurityEventsFired ("john" );
208245 }
209246
210247 @ Test
@@ -224,6 +261,7 @@ void shouldSecureMultiEndpointWithBlockingHttpSecurityPolicy() {
224261 .until (() -> results .size () == 5 );
225262
226263 assertThat (results .stream ().filter (e -> !e )).isEmpty ();
264+ assertSecurityEventsFired ("paul" );
227265 }
228266
229267 @ Test
@@ -241,6 +279,19 @@ void shouldSecureBlockingMultiEndpointWithBlockingHttpSecurityPolicy() {
241279 .until (() -> results .size () == 5 );
242280
243281 assertThat (results .stream ().filter (e -> e )).isEmpty ();
282+ assertSecurityEventsFired ("paul" );
283+ }
284+
285+ private void assertSecurityEventsFired (String username ) {
286+ // expect at least authentication success and RolesAllowed security check success
287+ // we don't check exact count as HTTP Security policies are not supported when gRPC is running on separate server
288+ assertTrue (securityEventObserver .getStorage ().size () >= 2 );
289+ assertTrue (securityEventObserver .getStorage ().stream ().anyMatch (e -> e instanceof AuthenticationSuccessEvent ));
290+ AuthorizationSuccessEvent event = (AuthorizationSuccessEvent ) securityEventObserver .getStorage ()
291+ .get (securityEventObserver .getStorage ().size () - 1 );
292+ assertNotNull (event .getSecurityIdentity ());
293+ assertEquals (username , event .getSecurityIdentity ().getPrincipal ().getName ());
294+ assertEquals (RolesAllowedCheck .class .getName (), event .getEventProperties ().get (AUTHORIZATION_CONTEXT ));
244295 }
245296
246297 private static void addBlockingHeaders (Metadata headers ) {
0 commit comments