2020import com .sun .enterprise .deployment .Application ;
2121import com .sun .enterprise .deployment .EjbBundleDescriptor ;
2222import com .sun .enterprise .deployment .WebBundleDescriptor ;
23+ import com .sun .enterprise .deployment .WebBundleRuntimeContext ;
2324import com .sun .enterprise .deployment .web .LoginConfiguration ;
2425import com .sun .enterprise .security .AppCNonceCacheMap ;
2526import com .sun .enterprise .security .CNonceCacheFactory ;
3334import jakarta .inject .Inject ;
3435import jakarta .inject .Named ;
3536import jakarta .inject .Provider ;
37+ import jakarta .servlet .ServletContext ;
3638
3739import java .util .ArrayList ;
3840import java .util .Collection ;
5759import org .glassfish .internal .data .ModuleInfo ;
5860import org .glassfish .security .common .CNonceCache ;
5961import org .glassfish .security .common .HAUtil ;
62+ import org .glassfish .soteria .rest .RestPermissions ;
6063import org .jvnet .hk2 .annotations .Service ;
6164
62- import static com .sun .enterprise .deployment .WebBundleDescriptor .AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT ;
65+ import static com .sun .enterprise .deployment .WebBundleRuntimeContext .AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT ;
66+ import static com .sun .enterprise .deployment .WebBundleRuntimeContext .AFTER_SERVLET_LOAD_INITIALIZED_EVENT ;
6367import static com .sun .enterprise .security .ee .authorization .AuthorizationUtil .getContextID ;
6468import static com .sun .enterprise .security .ee .authorization .AuthorizationUtil .removeRoleMapper ;
6569import static com .sun .enterprise .util .Utility .isEmpty ;
@@ -77,6 +81,8 @@ public class SecurityDeployer extends SimpleDeployer<SecurityContainer, DummyApp
7781
7882 private static final Logger LOGGER = LogDomains .getLogger (SecurityDeployer .class , LogDomains .SECURITY_LOGGER );
7983
84+ private static final String WEBBUNDLE_KEY = "org.glassfish.web.deployment.descriptor.WebBundleDescriptorImpl" ;
85+
8086 @ Inject
8187 private ServerContext serverContext ;
8288
@@ -115,15 +121,31 @@ private class AppDeployEventListener implements EventListener {
115121 public void event (Event <?> event ) {
116122 Application application ;
117123
124+ // Overview of the events regarding to the Policy permissions:
125+ //
126+ // MODULE_LOADED / generateArtifacts
127+ // -> initial policy translation without ServletContext
128+ //
129+ // APPLICATION_LOADED
130+ // -> link web/EJB policies
131+ // -> commit EJB policies
132+ //
133+ // AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT
134+ // -> if ServletContextListeners modified security, retranslate + commit
135+ //
136+ // AFTER_SERVLET_LOAD_INITIALIZED_EVENT
137+ // -> if Jersey/Soteria staged REST permissions, retranslate + final commit
138+
118139 if (MODULE_LOADED .equals (event .type ())) {
119140 ModuleInfo moduleInfo = (ModuleInfo ) event .hook ();
120141 if (moduleInfo instanceof ApplicationInfo ) {
121142 return ;
122143 }
123144
124- WebBundleDescriptor webBundleDescriptor = (WebBundleDescriptor )
125- moduleInfo .getMetaData ("org.glassfish.web.deployment.descriptor.WebBundleDescriptorImpl" );
126- loadWebPolicy (webBundleDescriptor , false );
145+ loadWebPolicy (
146+ null ,
147+ (WebBundleDescriptor ) moduleInfo .getMetaData (WEBBUNDLE_KEY ),
148+ false );
127149
128150 } else if (APPLICATION_LOADED .equals (event .type ())) {
129151 ApplicationInfo applicationInfo = (ApplicationInfo ) event .hook ();
@@ -144,8 +166,8 @@ public void event(Event<?> event) {
144166 handler .register ();
145167 }
146168 }
147- } else if (AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT .equals (event .type ())) {
148- commitWebPolicy ((WebBundleDescriptor ) event .hook ());
169+ } else if (AFTER_SERVLET_LOAD_INITIALIZED_EVENT . equals ( event . type ()) || AFTER_SERVLET_CONTEXT_INITIALIZED_EVENT .equals (event .type ())) {
170+ commitWebPolicy ((WebBundleRuntimeContext ) event .hook ());
149171 }
150172 }
151173 }
@@ -168,21 +190,22 @@ protected void generateArtifacts(DeploymentContext deploymentContext) throws Dep
168190 return ;
169191 }
170192
171- String applicationName = params .name ();
172193 try {
173- Application application = deploymentContext .getModuleMetaData (Application .class );
174- Set <WebBundleDescriptor > webBundleDescriptors = application .getBundleDescriptors (WebBundleDescriptor .class );
194+ Set <WebBundleDescriptor > webBundleDescriptors =
195+ deploymentContext .getModuleMetaData (Application .class )
196+ .getBundleDescriptors (WebBundleDescriptor .class );
197+
175198 if (webBundleDescriptors == null ) {
176199 return ;
177200 }
178201
179202 for (WebBundleDescriptor webBundleDescriptor : webBundleDescriptors ) {
180203 webBundleDescriptor .setApplicationClassLoader (deploymentContext .getFinalClassLoader ());
181- loadWebPolicy (webBundleDescriptor , false );
204+ loadWebPolicy (null , webBundleDescriptor , false );
182205 }
183206
184207 } catch (Exception se ) {
185- throw new DeploymentException ("Error in generating security policy for " + applicationName , se );
208+ throw new DeploymentException ("Error in generating security policy for " + params . name () , se );
186209 }
187210 }
188211
@@ -231,7 +254,7 @@ public void unload(DummyApplication container, DeploymentContext context) {
231254 * @param remove boolean indicated whether any existing policy statements are removed form context before translation
232255 * @throws DeploymentException
233256 */
234- private void loadWebPolicy (WebBundleDescriptor webBundleDescriptor , boolean remove ) throws DeploymentException {
257+ private void loadWebPolicy (ServletContext servletContext , WebBundleDescriptor webBundleDescriptor , boolean remove ) throws DeploymentException {
235258 try {
236259 if (webBundleDescriptor != null ) {
237260 if (remove ) {
@@ -241,7 +264,7 @@ private void loadWebPolicy(WebBundleDescriptor webBundleDescriptor, boolean remo
241264 webSecurityManager .release ();
242265 }
243266 }
244- webSecurityManagerFactory .createManager (webBundleDescriptor , true , serverContext );
267+ webSecurityManagerFactory .createManager (servletContext , webBundleDescriptor , true , serverContext );
245268 }
246269
247270 } catch (Exception se ) {
@@ -251,17 +274,34 @@ private void loadWebPolicy(WebBundleDescriptor webBundleDescriptor, boolean remo
251274 }
252275
253276 /**
254- * Puts Web Bundle Policy In Service, repeats translation if Descriptor indicates policy was changed by ContextListener .
277+ * Commits the web policy at servlet lifecycle milestones .
255278 *
256- * @param webBundleDescriptor
279+ * <p>
280+ * This method may commit more than once during startup. The first commit, after
281+ * ServletContextListener processing, makes the policy available to subsequent
282+ * initialization code such as filter init and load-on-startup servlet init.
283+ *
284+ * <p>
285+ * Later, load-on-startup servlet initialization may discover additional security
286+ * metadata, notably Jakarta REST endpoint security staged by Soteria. If so, the
287+ * policy is reopened, rebuilt from the full effective web model, and committed
288+ * again before the module is made available for requests.
289+ *
290+ * @param webBundleRuntimeContext
257291 * @throws DeploymentException
258292 */
259- private void commitWebPolicy (WebBundleDescriptor webBundleDescriptor ) throws DeploymentException {
293+ private void commitWebPolicy (WebBundleRuntimeContext webBundleRuntimeContext ) throws DeploymentException {
294+ WebBundleDescriptor webBundleDescriptor = webBundleRuntimeContext .webBundleDescriptor ();
295+ ServletContext servletContext = webBundleRuntimeContext .servletContext ();
296+
260297 try {
261298 if (webBundleDescriptor != null ) {
262- if (webBundleDescriptor .isPolicyModified ()) {
299+ if (webBundleDescriptor .isPolicyModified () || RestPermissions . hasPermissions ( servletContext ) ) {
263300 // Redo policy translation for web module
264- loadWebPolicy (webBundleDescriptor , true );
301+ loadWebPolicy (servletContext , webBundleDescriptor , true );
302+
303+ webBundleDescriptor .setPolicyModified (false );
304+ RestPermissions .clear (servletContext );
265305 }
266306
267307 String contextId = getContextID (webBundleDescriptor );
0 commit comments