Repository: apache/streampipes
Pull request #2718 (2024-04-09 09:52:03)

refactor: consolidate duplicated code used for secure string generation
<!--
  ~ Licensed to the Apache Software Foundation (ASF) under one or more
  ~ contributor license agreements.  See the NOTICE file distributed with
  ~ this work for additional information regarding copyright ownership.
  ~ The ASF licenses this file to You under the Apache License, Version 2.0
  ~ (the "License"); you may not use this file except in compliance with
  ~ the License.  You may obtain a copy of the License at
  ~
  ~    http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  -->
  
  <!--
Thanks for contributing! Here are some tips you can follow to help us incorporate your contribution quickly and easily:
1. If this is your first time, please read our contributor guidelines:
    - https://streampipes.apache.org/getinvolved.html
    - https://cwiki.apache.org/confluence/display/STREAMPIPES/Getting+Started
2. Make sure the PR title is formatted like: `[#<GitHub issue id>] PR title ...`
3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., `[WIP][#<GitHub issue id>] PR title ...`.
4. Please write your PR title to summarize what this PR proposes/fixes.
5. Link the PR to the corresponding GitHub issue (if present) in the `Development` section in the right menu bar. 
6. Be sure to keep the PR description updated to reflect all changes.
7. If possible, provide a concise example to reproduce the issue for a faster review.
8. Make sure tests pass via `mvn clean install`.
9. (Optional) If the contribution is large, please file an Apache ICLA
    - http://apache.org/licenses/icla.pdf
-->

### Purpose
<!--
Please clarify what changes you are proposing and describe how those changes will address the issue.
Furthermore, describe potential consequences the changes might have.
-->

### Remarks
<!--
Is there anything left we need to pay attention on?
Are there some references that might be important? E.g. links to Confluence, or discussions
on the mailing list or GitHub.
-->
PR introduces (a) breaking change(s): <yes/no>

PR introduces (a) deprecation(s): <yes/no>



Patch:
diff --git a/streampipes-maven-plugin/pom.xml b/streampipes-maven-plugin/pom.xml
index ecb4047a25..456c90c211 100644
--- a/streampipes-maven-plugin/pom.xml
+++ b/streampipes-maven-plugin/pom.xml
@@ -40,7 +40,7 @@
         <maven-deploy-plugin.version>3.1.0</maven-deploy-plugin.version>
         <maven-install-plugin.version>3.1.1</maven-install-plugin.version>
         <maven-invoker-plugin.version>3.6.0</maven-invoker-plugin.version>
-        <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
+        <maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
         <maven-plugin-plugin.version>3.12.0</maven-plugin-plugin.version>
         <maven-resources-plugin.version>3.3.0</maven-resources-plugin.version>
         <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/PasswordUtil.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/PasswordUtil.java
index 779636ec48..c1a8c95078 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/PasswordUtil.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/PasswordUtil.java
@@ -18,8 +18,6 @@
 
 package org.apache.streampipes.user.management.util;
 
-import org.apache.commons.text.RandomStringGenerator;
-
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 
@@ -31,6 +29,7 @@ import java.security.spec.InvalidKeySpecException;
 public class PasswordUtil {
 
   private static final int DEFAULT_PASSWORD_LENGTH = 10;
+  private static final String SECRET_KEY_ALGORITHM_NAME = "PBKDF2WithHmacSHA1";
 
   public static byte[] createSalt() {
     SecureRandom random = new SecureRandom();
@@ -46,7 +45,7 @@ public class PasswordUtil {
     byte[] salt = createSalt();
 
     PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 64 * 8);
-    SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+    SecretKeyFactory skf = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM_NAME);
     byte[] hash = skf.generateSecret(spec).getEncoded();
     return iterations + ":" + toHex(salt) + ":" + toHex(hash);
   }
@@ -71,7 +70,7 @@ public class PasswordUtil {
 
     PBEKeySpec spec = new PBEKeySpec(originalProperty.toCharArray(), salt, iterations,
         hash.length * 8);
-    SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+    SecretKeyFactory skf = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM_NAME);
     byte[] testHash = skf.generateSecret(spec).getEncoded();
 
     int diff = hash.length ^ testHash.length;
@@ -92,11 +91,6 @@ public class PasswordUtil {
 
 
   public static String generateRandomPassword() {
-
-    // allowing all ASCII-characters from decimal id 33 to 125
-    // see https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html for full list
-    var pwdGenerator = new RandomStringGenerator.Builder().withinRange(33, 125)
-            .build();
-    return pwdGenerator.generate(DEFAULT_PASSWORD_LENGTH);
+    return new SecureStringGenerator().generateSecureString(DEFAULT_PASSWORD_LENGTH);
   }
 }
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/SecureStringGenerator.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/SecureStringGenerator.java
new file mode 100644
index 0000000000..046f0da2b0
--- /dev/null
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/SecureStringGenerator.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.user.management.util;
+
+import org.apache.commons.text.RandomStringGenerator;
+
+import java.security.SecureRandom;
+
+public class SecureStringGenerator {
+  public String generateSecureString(int length) {
+    // allowing all ASCII-characters from decimal id 33 to 125
+    // see https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html for full list
+    var pwdGenerator = new RandomStringGenerator.Builder().usingRandom(new SecureRandom()::nextInt)
+        .withinRange(33, 125)
+        .build();
+    return pwdGenerator.generate(length);
+  }
+}
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/TokenUtil.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/TokenUtil.java
index 2233c8c20e..2b642d82cd 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/TokenUtil.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/TokenUtil.java
@@ -21,7 +21,6 @@ import org.apache.streampipes.model.client.user.RawUserApiToken;
 import org.apache.streampipes.model.client.user.UserApiToken;
 
 import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.text.RandomStringGenerator;
 
 import java.util.UUID;
 
@@ -48,20 +47,12 @@ public class TokenUtil {
     return userApiToken;
   }
 
-  public static boolean validateToken(String providedToken, String hashedToken) {
-    return hashToken(providedToken).equals(hashedToken);
-  }
-
   private static String generateToken() {
     return generateToken(TOKEN_LENGTH);
   }
 
-  public static String generateToken(int tokenLength){
-    // allowing all ASCII-characters from decimal id 33 to 125
-    // see https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html for full list
-    var pwdGenerator = new RandomStringGenerator.Builder().withinRange(33, 125)
-                                                          .build();
-    return pwdGenerator.generate(tokenLength);
+  public static String generateToken(int tokenLength) {
+    return new SecureStringGenerator().generateSecureString(tokenLength);
   }
 
   public static String hashToken(String token) {
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 9e343591ad..be79f200cc 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -59,7 +59,7 @@
         "rxjs": "^7.8.0",
         "shepherd.js": "^11.2.0",
         "stream-browserify": "3.0.0",
-        "swagger-ui-dist": "5.13.0",
+        "swagger-ui-dist": "5.14.0",
         "tslib": "^2.6.2",
         "zone.js": "~0.14.4"
       },
@@ -19904,9 +19904,9 @@
       }
     },
     "node_modules/swagger-ui-dist": {
-      "version": "5.13.0",
-      "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.13.0.tgz",
-      "integrity": "sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q=="
+      "version": "5.14.0",
+      "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.14.0.tgz",
+      "integrity": "sha512-7qsKvc3gs5dnEIOclY4xkzacY85Pu9a/Gzkf+eezKLQ4BpErlI8BxYWADhnCx6PmFyU4fxH4AMKH+/d3Kml0Gg=="
     },
     "node_modules/symbol-observable": {
       "version": "4.0.0",
diff --git a/ui/package.json b/ui/package.json
index 948d3e9d89..4779b5e1a0 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -80,7 +80,7 @@
     "rxjs": "^7.8.0",
     "shepherd.js": "^11.2.0",
     "stream-browserify": "3.0.0",
-    "swagger-ui-dist": "5.13.0",
+    "swagger-ui-dist": "5.14.0",
     "tslib": "^2.6.2",
     "zone.js": "~0.14.4"
   },
diff --git a/ui/src/app/assets/assets.module.ts b/ui/src/app/assets/assets.module.ts
index 8c912ecae5..b7c0af37be 100644
--- a/ui/src/app/assets/assets.module.ts
+++ b/ui/src/app/assets/assets.module.ts
@@ -44,6 +44,9 @@ import { EditAssetLinkDialogComponent } from './dialog/edit-asset-link/edit-asse
 import { SpCreateAssetDialogComponent } from './dialog/create-asset/create-asset-dialog.component';
 import { SpManageAssetLinksDialogComponent } from './dialog/manage-asset-links/manage-asset-links-dialog.component';
 import { MatTableModule } from '@angular/material/table';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSidenavModule } from '@angular/material/sidenav';
+import { MatSelectModule } from '@angular/material/select';
 
 @NgModule({
     imports: [
@@ -54,9 +57,12 @@ import { MatTableModule } from '@angular/material/table';
         MatProgressSpinnerModule,
         MatIconModule,
         MatInputModule,
+        MatFormFieldModule,
         MatTableModule,
         MatCheckboxModule,
         MatDividerModule,
+        MatSidenavModule,
+        MatSelectModule,
         MatTooltipModule,
         FormsModule,
         DragDropModule,


Test patch:
diff --git a/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestPasswordUtil.java b/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestSecureStringGenerator.java
similarity index 79%
rename from streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestPasswordUtil.java
rename to streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestSecureStringGenerator.java
index 62037b7131..fc30f9b732 100644
--- a/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestPasswordUtil.java
+++ b/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestSecureStringGenerator.java
@@ -21,17 +21,17 @@ import com.google.common.base.CharMatcher;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import static org.apache.streampipes.user.management.util.PasswordUtil.generateRandomPassword;
-
-public class TestPasswordUtil {
+public class TestSecureStringGenerator {
 
   @Test
-  public void testGenerateRandomPassword() {
+  public void testGenerateSecureString() {
+
+    var stringLength = 10;
 
-    String randomPassword = generateRandomPassword();
+    String randomPassword = new SecureStringGenerator().generateSecureString(stringLength);
 
     Assertions.assertNotNull(randomPassword);
-    Assertions.assertEquals(10, randomPassword.length());
+    Assertions.assertEquals(stringLength, randomPassword.length());
     Assertions.assertTrue(CharMatcher.ascii().matchesAllOf(randomPassword));
   }
 
diff --git a/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestTokenUtil.java b/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestTokenUtil.java
deleted file mode 100644
index 75cd2d5d60..0000000000
--- a/streampipes-user-management/src/test/java/org/apache/streampipes/user/management/util/TestTokenUtil.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.streampipes.user.management.util;
-
-import org.apache.streampipes.model.client.user.RawUserApiToken;
-import org.apache.streampipes.model.client.user.UserApiToken;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class TestTokenUtil {
-
-  @Test
-  public void testCreateToken() {
-    String tokenName = "test-token";
-
-    RawUserApiToken rawToken = TokenUtil.createToken(tokenName);
-    Assertions.assertEquals("test-token", rawToken.getTokenName());
-    Assertions.assertNotNull(rawToken.getTokenId());
-    Assertions.assertNotNull(rawToken.getRawToken());
-    Assertions.assertNotNull(rawToken.getHashedToken());
-  }
-
-  @Test
-  public void testToUserToken() {
-    RawUserApiToken rawToken = TokenUtil.createToken("test-token");
-    UserApiToken token = TokenUtil.toUserToken(rawToken);
-
-    Assertions.assertEquals(rawToken.getHashedToken(), token.getHashedToken());
-    Assertions.assertEquals(rawToken.getTokenId(), token.getTokenId());
-    Assertions.assertEquals(rawToken.getTokenName(), token.getTokenName());
-  }
-
-  @Test
-  public void testTokenValidation() {
-    RawUserApiToken rawToken = TokenUtil.createToken("test-token");
-    String rawApiKey = rawToken.getRawToken();
-
-    Assertions.assertTrue(TokenUtil.validateToken(rawApiKey, rawToken.getHashedToken()));
-  }
-
-}