[java-plugin-shibd] 01/02: Updates to sealer operation contract.

Codeberg noreply at shibboleth.net
Mon Sep 21 19:49:54 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-plugin-shibd.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/49f774fb0773c102db824fd1abbf98af918aa6d6

commit 49f774fb0773c102db824fd1abbf98af918aa6d6
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Sep 21 15:49:26 2026 -0400

    Updates to sealer operation contract.
---
 .../net/shibboleth/sp/flows/SealerFlowTest.java    | 58 +++++++++----
 .../sp/profile/impl/DoSealerOperation.java         | 77 +++++++++---------
 .../sp/profile/impl/DoSealerOperationTest.java     | 94 +++++++++-------------
 3 files changed, 119 insertions(+), 110 deletions(-)

diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
index c8add88..141b437 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
@@ -73,10 +73,10 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
     
     /**
-     * Test wrap operation with no input.
+     * Test missing operation.
      */
     @Test
-    public void testWrapNoInput() {
+    public void testMissingOperation() {
         setDefaultAuth();
         request.setMethod("POST");
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -86,16 +86,35 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
     
     /**
-     * Test wrap operation with pre-expired data.
+     * Test encrypt operation with no input.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void testEncryptNoInput() throws IOException {
+        setDefaultAuth();
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("E");
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+    }
+    
+    /**
+     * Test encrypt operation with pre-expired data.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void testWrapExpired() throws IOException, DataSealerException {
+    public void testEncryptExpired() throws IOException, DataSealerException {
         setDefaultAuth();
 
         final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("E");
         input.addmember(DoSealerOperation.VALUE).string(TEST_VALUE);
         input.addmember(DoSealerOperation.EXP).longinteger(Instant.now().minusSeconds(3600).toEpochMilli() / 1000);
         setRequest("POST", input);
@@ -117,16 +136,17 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
 
     /**
-     * Test wrap operation success.
+     * Test encrypt operation success.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void testWrapSuccess() throws IOException, DataSealerException {
+    public void testEncryptSuccess() throws IOException, DataSealerException {
         setDefaultAuth();
 
         final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("E");
         input.addmember(DoSealerOperation.VALUE).string(TEST_VALUE);
         setRequest("POST", input);
         
@@ -142,12 +162,18 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
 
     /**
-     * Test unwrap operation with no input.
+     * Test decrypt operation with no input.
+     * 
+     * @throws IOException 
      */
     @Test
-    public void testUnwrapNoInput() {
+    public void testDecryptNoInput() throws IOException {
         setDefaultAuth();
-        request.setMethod("GET");
+
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("D");
+        setRequest("POST", input);
+        
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
         assertFlowExecutionOutcome(result.getOutcome());
@@ -155,20 +181,21 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
     
     /**
-     * Test unwrap operation with pre-expired data.
+     * Test decrypt operation with pre-expired data.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void testUnrrapExpired() throws IOException, DataSealerException {
+    public void testDecryptExpired() throws IOException, DataSealerException {
         setDefaultAuth();
 
         final String wrapped = getDataSealer().wrap(AGENT_ID + '!' + TEST_VALUE, Instant.now().minusSeconds(3600));
         
         final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("D"); 
         input.addmember(DoSealerOperation.VALUE).string(wrapped);
-        setRequest("GET", input);
+        setRequest("POST", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
@@ -177,20 +204,21 @@ public class SealerFlowTest extends AbstractSPFlowTest {
     }
 
     /**
-     * Test unwrap operation success.
+     * Test decrypt operation success.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void testUnwrapSuccess() throws IOException, DataSealerException {
+    public void testDecryptSuccess() throws IOException, DataSealerException {
         setDefaultAuth();
 
         final String wrapped = getDataSealer().wrap(AGENT_ID + '!' + TEST_VALUE, Instant.now().plusSeconds(3600));
         
         final DDF input = new DDF("sealer").structure();
+        input.addmember(DoSealerOperation.OP).string("D");
         input.addmember(DoSealerOperation.VALUE).string(wrapped);
-        setRequest("GET", input);
+        setRequest("POST", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSealerOperation.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSealerOperation.java
index 0eb4b97..ff48ad4 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSealerOperation.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/DoSealerOperation.java
@@ -35,7 +35,6 @@ import net.shibboleth.shared.security.DataSealerException;
 import net.shibboleth.sp.Agent;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.AbstractAgentAction;
-import jakarta.servlet.http.HttpServletRequest;
 
 /**
  * Action that implements a remote API for SP agents to leverage a {@link DataSealer}.
@@ -43,7 +42,7 @@ import jakarta.servlet.http.HttpServletRequest;
  * <p>All contexts are prefixed with {@link Agent#getId} to prevent conflicts across agents.</p>
  * 
  * @event {@link EventIds#PROCEED_EVENT_ID}
- * @event {@link EventIds#INVALID_PROFILE_CTX}
+ * @event {@link EventIds#INVALID_MSG_CTX}
  * @event {@link EventIds#ACCESS_DENIED}
  * @event {@link EventIds#INVALID_MESSAGE}
  * @event {@link EventIds#MESSAGE_PROC_ERROR}
@@ -52,6 +51,9 @@ import jakarta.servlet.http.HttpServletRequest;
  */
 public class DoSealerOperation extends AbstractAgentAction {
 
+    /** Member for operation code. */
+    @Nonnull @NotEmpty public static final String OP = "op";
+
     /** Member for storage value. */
     @Nonnull @NotEmpty public static final String VALUE = "value";
 
@@ -97,10 +99,6 @@ public class DoSealerOperation extends AbstractAgentAction {
         
         if (!super.doPreExecute(profileRequestContext)) {
             return false;
-        } else if (getHttpServletRequest() == null) {
-            log.warn("{} No HttpServletRequest available", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
-            return false;
         }
         
         input = ensureAgentRequestContext().getInput();
@@ -113,7 +111,7 @@ public class DoSealerOperation extends AbstractAgentAction {
         output = ensureAgentRequestContext().getOutput();
         if (output == null || !output.isstruct()) {
             log.warn("{} Invalid or missing output message", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
             return false;
         }
 
@@ -124,14 +122,14 @@ public class DoSealerOperation extends AbstractAgentAction {
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         
         try {
-            final HttpServletRequest request = ensureHttpServletRequest();
+            final String op = input.getmember(OP).string();
             
-            if ("GET".equals(request.getMethod())) {
-                doUnwrap(profileRequestContext);
-            } else if ("POST".equals(request.getMethod())) {
+            if ("E".equals(op)) {
                 doWrap(profileRequestContext);
+            } else if ("D".equals(op)) {
+                doUnwrap(profileRequestContext);
             } else {
-                log.warn("{} Invalid method: {}", getLogPrefix(), request.getMethod());
+                log.warn("{} Invalid {} value: {}", getLogPrefix(), OP, op);
                 ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             }
         } catch (final DataSealerException e) {
@@ -140,6 +138,30 @@ public class DoSealerOperation extends AbstractAgentAction {
         }
     }
     
+    /**
+     * Perform wrap operation.
+     * 
+     * @param profileRequestContext profile request context
+     * 
+     * @throws DataSealerException if an error is raised
+     */
+    private void doWrap(@Nonnull final ProfileRequestContext profileRequestContext) throws DataSealerException {
+        
+        String unwrapped = input.getmember(VALUE).string();
+        if (unwrapped == null) {
+            log.warn("{} No {} parameter supplied for encryption operation", getLogPrefix(), VALUE);
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+            return;
+        }
+        
+        final Long exp = input.getmember(EXP).longinteger();
+
+        final String wrapped = dataSealer.wrap(ensureAgent().getId() + '!' + unwrapped,
+                exp != null ? Instant.ofEpochSecond(exp) : null);
+        
+        output.addmember(VALUE).string(wrapped);
+    }
+    
     /**
      * Perform unwrap operation.
      * 
@@ -151,7 +173,7 @@ public class DoSealerOperation extends AbstractAgentAction {
         
         final String wrapped = input.getmember(VALUE).string();
         if (wrapped == null) {
-            log.warn("{} No value parameter supplied for unwrap operation", getLogPrefix());
+            log.warn("{} No {} parameter supplied for decryption operation", getLogPrefix(), VALUE);
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
             return;
         }
@@ -160,7 +182,7 @@ public class DoSealerOperation extends AbstractAgentAction {
         try {
             unwrapped = dataSealer.unwrap(wrapped);
         } catch (final DataExpiredException e) {
-            log.info("{} Decrypted data was expired", getLogPrefix());
+            log.info("{} Decrypted data has expired", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_EXPIRED);
             return;
         }
@@ -169,34 +191,9 @@ public class DoSealerOperation extends AbstractAgentAction {
         if (unwrapped.startsWith(prefix)) {
             output.addmember(VALUE).string(unwrapped.substring(prefix.length()));
         } else {
-            log.warn("{} Encrypted data was not created by this agent", getLogPrefix());
+            log.warn("{} Encrypted data was not created by this Agent", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
         }
     }
     
-    
-    /**
-     * Perform wrap operation.
-     * 
-     * @param profileRequestContext profile request context
-     * 
-     * @throws DataSealerException if an error is raised
-     */
-    private void doWrap(@Nonnull final ProfileRequestContext profileRequestContext) throws DataSealerException {
-        
-        String unwrapped = input.getmember(VALUE).string();
-        if (unwrapped == null) {
-            log.warn("{} No value parameter supplied for wrap operation", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
-            return;
-        }
-        
-        final Long exp = input.getmember(EXP).longinteger();
-
-        final String wrapped = dataSealer.wrap(ensureAgent().getId() + '!' + unwrapped,
-                exp != null ? Instant.ofEpochSecond(exp) : null);
-        
-        output.addmember(VALUE).string(wrapped);
-    }
-    
 }
\ No newline at end of file
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/DoSealerOperationTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/DoSealerOperationTest.java
index b5914f1..57b7f13 100644
--- a/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/DoSealerOperationTest.java
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/DoSealerOperationTest.java
@@ -105,6 +105,7 @@ public class DoSealerOperationTest extends BaseAgentRequestTest {
         super.beforeMethod();
         
         request = (MockHttpServletRequest) src.getExternalContext().getNativeRequest();
+        request.setMethod("POST");
 
         dataSealer = createDataSealer("one");
         dataSealer.initialize();
@@ -130,118 +131,104 @@ public class DoSealerOperationTest extends BaseAgentRequestTest {
     }
 
     /**
-     * Test invalidMethod
+     * Test request with no operation
      */
     @Test
-    public void invalidMethod() {
-        
-        arc.setInput(new DDF().structure());
-        
-        request.setMethod("FOO");
+    public void noOperation() {
+        arc.setInput(new DDF("sealer").structure());
+
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.INVALID_MESSAGE);
     }
 
-
     /**
-     * Test unwrap with no inputs.
+     * Test encrypt with no inputs.
      */
     @Test
-    public void noParamsUnwrap() {
-        arc.setInput(new DDF().structure());
+    public void noParamsEncrypt() {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("E");
+        arc.setInput(input);
+
 
-        request.setMethod("GET");
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.INVALID_MESSAGE);
     }
-
+    
     /**
-     * Test wrap with no inputs.
+     * Test decrypt with no inputs.
      */
     @Test
-    public void noParamsWrap() {
-        arc.setInput(new DDF().structure());
+    public void noParamsDecrypt() {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("D");
+        arc.setInput(input);
+
 
-        request.setMethod("POST");
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.INVALID_MESSAGE);
     }
 
     /**
-     * Test unwrap with bogus data.
+     * Test decrypt with bogus data.
      */
     @Test
-    public void invalidDataUnwrap() {
-        
-        request.setMethod("GET");
-        
-        final DDF input = new DDF().structure();
+    public void invalidDataDecrypt() {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("D");
         input.addmember(DoSealerOperation.VALUE).string("foo");
         arc.setInput(input);
         
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.MESSAGE_PROC_ERROR);
     }
 
     /**
-     * Test unwrap with expired data.
+     * Test decrypt with expired data.
      * 
      * @throws DataSealerException 
      */
     @Test
-    public void expiredDataUnwrap() throws DataSealerException {
-        
-        request.setMethod("GET");
-        
-        final DDF input = new DDF().structure();
+    public void expiredDataDecrypt() throws DataSealerException {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("D");
         input.addmember(DoSealerOperation.VALUE).string(dataSealer.wrap(VALUE, Instant.now().minusSeconds(3600)));
         arc.setInput(input);
         
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.MESSAGE_EXPIRED);
     }
 
     /**
-     * Test unwrap with wrong agent's data.
+     * Test decrypt with wrong agent's data.
      * 
      * @throws DataSealerException 
      */
     @Test
-    public void wrongDataUnwrap() throws DataSealerException {
-        
-        request.setMethod("GET");
-        
-        final DDF input = new DDF().structure();
-        input.addmember(DoSealerOperation.VALUE).string(dataSealer.wrap(VALUE, Instant.now().plusSeconds(3600)));
+    public void wrongDataDecrypt() throws DataSealerException {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("D");
+        input.addmember(DoSealerOperation.VALUE).string(dataSealer.wrap(agent.getId() + '2' + '!' + VALUE, Instant.now().plusSeconds(3600)));
         arc.setInput(input);
         
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertEvent(event, EventIds.ACCESS_DENIED);
     }
 
     /**
-     * Test successful unwrap.
+     * Test successful decrypt.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void unwrap() throws IOException, DataSealerException {
-        
-        request.setMethod("GET");
-        
-        final DDF input = new DDF().structure();
+    public void decrypt() throws IOException, DataSealerException {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("D");
         input.addmember(DoSealerOperation.VALUE).string(dataSealer.wrap(agent.getId() + '!' + VALUE, Instant.now().plusSeconds(3600)));
         arc.setInput(input);
         
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertProceedEvent(event);
 
         final DDF output = arc.getOutput();
@@ -251,22 +238,19 @@ public class DoSealerOperationTest extends BaseAgentRequestTest {
     }    
 
     /**
-     * Test successful wrap.
+     * Test successful encrypt.
      * 
      * @throws IOException 
      * @throws DataSealerException 
      */
     @Test
-    public void wrap() throws IOException, DataSealerException {
-        
-        request.setMethod("POST");
-        
-        final DDF input = new DDF().structure();
+    public void encrypt() throws IOException, DataSealerException {
+        final DDF input = new DDF("sealer").structure();
+        input.addmember(DoStorageOperation.OP).string("E");
         input.addmember(DoSealerOperation.VALUE).string(VALUE);
         arc.setInput(input);
         
         final Event event = action.execute(src);
-        
         ActionTestingSupport.assertProceedEvent(event);
 
         final DDF output = arc.getOutput();

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list