This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 8f70ba9  KNOX-2606 - Indicate configured token TTL on UI and ask for 
confirmation when end-users try to generate a token above the configured limit 
(#450)
8f70ba9 is described below

commit 8f70ba9a20d941ccab9510d298744d1f04bd71f2
Author: Sandor Molnar <[email protected]>
AuthorDate: Thu May 20 22:40:19 2021 +0200

    KNOX-2606 - Indicate configured token TTL on UI and ask for confirmation 
when end-users try to generate a token above the configured limit (#450)
---
 .../resources/applications/tokengen/app/index.html |  4 +++
 .../applications/tokengen/app/js/tokengen.js       | 34 ++++++++++++++++++-
 .../gateway/service/knoxtoken/TokenResource.java   | 38 +++++++++++++++++++++-
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git 
a/gateway-applications/src/main/resources/applications/tokengen/app/index.html 
b/gateway-applications/src/main/resources/applications/tokengen/app/index.html
index 921d85b..ddd8d56 100644
--- 
a/gateway-applications/src/main/resources/applications/tokengen/app/index.html
+++ 
b/gateway-applications/src/main/resources/applications/tokengen/app/index.html
@@ -32,6 +32,7 @@
 
         <script src="libs/bower/jquery/js/jquery-3.5.1.min.js" ></script>
         <script type="text/javascript" src="js/tokengen.js"></script>
+        <script 
src="https://unpkg.com/sweetalert/dist/sweetalert.min.js";></script>
     
         <script type="text/javascript">
            $(function() {
@@ -65,6 +66,9 @@
                         <label><i class="icon-comment"></i> Comment:</label>
                         <input type="text" name="comment" id="comment" 
tabindex="1" onkeypress=keypressed(event) autofocus size="255">
 
+                        <label><i class="icon-info"></i> Configured maximum 
lifetime: </label>
+                        <label id="maximumLifetimeText"></label>
+                        <input type="number" id="maximumLifetimeSeconds" 
name="maximumLifetimeSeconds" style="display: none;">
                         <label><i class="icon-time"></i> Lifetime (days, 
hours, mins):</label>
                         <table>
                             <tr>
diff --git 
a/gateway-applications/src/main/resources/applications/tokengen/app/js/tokengen.js
 
b/gateway-applications/src/main/resources/applications/tokengen/app/js/tokengen.js
index 9e9dd70..f4a8236 100644
--- 
a/gateway-applications/src/main/resources/applications/tokengen/app/js/tokengen.js
+++ 
b/gateway-applications/src/main/resources/applications/tokengen/app/js/tokengen.js
@@ -104,6 +104,9 @@ function setTokenStateServiceStatus() {
                 } else {
                     disableTokenGen('Token management is disabled');
                 }
+
+                $('#maximumLifetimeText').text(resp.maximumLifetimeText);
+                $('#maximumLifetimeSeconds').text(resp.maximumLifetimeSeconds);
             }
         }
     }
@@ -133,6 +136,20 @@ function validateLifespan(days, hours, mins) {
     return valid;
 }
 
+function maximumLifetimeExceeded(maximumLifetime, days, hours, mins) {
+       if (maximumLifetime == -1) {
+               return false;
+       }
+
+    var daysInSeconds = days * 86400;
+    var hoursInSeconds = hours * 3600;
+    var minsInSeconds = mins * 60;
+    var suppliedLifetime = daysInSeconds + hoursInSeconds + minsInSeconds;
+    //console.debug("Supplied lifetime in seconds = " + suppliedLifetime);
+    //console.debug("Maximum lifetime = " + maximumLifetime);
+    return suppliedLifetime > maximumLifetime;
+}
+
 var gen = function() {
        $('#invalidLifetimeText').hide();
     var pathname = window.location.pathname;
@@ -188,6 +205,21 @@ var gen = function() {
     }
 
     if (validateLifespan(form.lt_days, form.lt_hours, form.lt_mins)) {
-        _gen();
+        if (maximumLifetimeExceeded(form.maximumLifetimeSeconds.textContent, 
lt_days, lt_hours, lt_mins)) {
+            swal({
+                title: "Warning",
+                text: "You are trying to generate a token with a lifetime that 
exceeds the configured maximum. In this case the generated token's lifetime 
will be limited to the configured maximum.",
+                icon: "warning",
+                buttons: ["Adjust request lifetime", "Generate token anyway"],
+                dangerMode: true
+              })
+              .then((willGenerateToken) => {
+                if (willGenerateToken) {
+                    _gen();
+                }
+              });
+          } else {
+              _gen();
+          }
     }
 }
diff --git 
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
 
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
index 41ea7eb..213969c 100644
--- 
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
+++ 
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
@@ -102,6 +102,8 @@ public class TokenResource {
   private static final String TSS_STATUS_CONFIFURED_BACKEND = 
"configuredTssBackend";
   private static final String TSS_STATUS_ACTUAL_BACKEND = "actualTssBackend";
   private static final String TSS_ALLOWED_BACKEND_FOR_TOKENGEN = 
"allowedTssForTokengen";
+  private static final String TSS_MAXIMUM_LIFETIME_SECONDS = 
"maximumLifetimeSeconds";
+  private static final String TSS_MAXIMUM_LIFETIME_TEXT = 
"maximumLifetimeText";
   private static final long TOKEN_TTL_DEFAULT = 30000L;
   static final String TOKEN_API_PATH = "knoxtoken/api/v1";
   static final String RESOURCE_PATH = TOKEN_API_PATH + "/token";
@@ -113,6 +115,7 @@ public class TokenResource {
   private static final String TARGET_ENDPOINT_PULIC_CERT_PEM = 
"knox.token.target.endpoint.cert.pem";
   private static TokenServiceMessages log = 
MessagesFactory.get(TokenServiceMessages.class);
   private long tokenTTL = TOKEN_TTL_DEFAULT;
+  private String tokenTTLAsText;
   private List<String> targetAudiences = new ArrayList<>();
   private String tokenTargetUrl;
   private Map<String, Object> tokenClientDataMap;
@@ -172,6 +175,7 @@ public class TokenResource {
         log.invalidTokenTTLEncountered(ttl);
       }
     }
+    tokenTTLAsText = getTokenTTLAsText();
 
     tokenTargetUrl = context.getInitParameter(TOKEN_TARGET_URL);
 
@@ -231,6 +235,32 @@ public class TokenResource {
     setTokenStateServiceStatusMap();
   }
 
+  private String getTokenTTLAsText() {
+    if (tokenTTL == -1) {
+      return "Unlimited lifetime";
+    }
+
+    final Duration tokenTTLDuration = Duration.ofMillis(tokenTTL);
+    long daysPart = tokenTTLDuration.toDays();
+    long hoursPart = daysPart > 0 ? 
tokenTTLDuration.minusDays(daysPart).toHours() : tokenTTLDuration.toHours();
+    long minutesPart = tokenTTLDuration.toHours() > 0 ? 
tokenTTLDuration.minusHours(tokenTTLDuration.toHours()).toMinutes() : 
tokenTTLDuration.toMinutes();
+    long secondsPart = tokenTTLDuration.toMinutes() > 0 ? 
tokenTTLDuration.minusMinutes(tokenTTLDuration.toMinutes()).getSeconds() : 
tokenTTLDuration.getSeconds();
+    final StringBuilder sb = new StringBuilder(32);
+    if (daysPart > 0) {
+      sb.append(daysPart).append(" days ");
+    }
+    if (hoursPart > 0) {
+      sb.append(hoursPart).append(" hours ");
+    }
+    if (minutesPart > 0) {
+      sb.append(minutesPart).append(" minutes ");
+    }
+    if (secondsPart > 0) {
+      sb.append(secondsPart).append(" seconds");
+    }
+    return sb.toString();
+  }
+
   private void setTokenStateServiceStatusMap() {
     if (isServerManagedTokenStateEnabled()) {
       tokenStateServiceStatusMap.put(TSS_STATUS_IS_MANAGEMENT_ENABLED, "true");
@@ -243,6 +273,8 @@ public class TokenResource {
       tokenStateServiceStatusMap.put(TSS_STATUS_CONFIFURED_BACKEND, 
configuredTokenServiceName);
       tokenStateServiceStatusMap.put(TSS_STATUS_ACTUAL_BACKEND, 
actualTokenServiceName);
       populateAllowedTokenStateBackendForTokenGenApp(actualTokenServiceName);
+      tokenStateServiceStatusMap.put(TSS_MAXIMUM_LIFETIME_SECONDS, 
String.valueOf(tokenTTL == -1 ? tokenTTL : (tokenTTL / 1000)));
+      tokenStateServiceStatusMap.put(TSS_MAXIMUM_LIFETIME_TEXT, 
tokenTTLAsText);
     } else {
       tokenStateServiceStatusMap.put(TSS_STATUS_IS_MANAGEMENT_ENABLED, 
"false");
     }
@@ -610,7 +642,11 @@ public class TokenResource {
     else {
       try {
         long lifetime = Duration.parse(lifetimeStr).toMillis();
-        if (lifetime <= tokenTTL) {
+        if (tokenTTL == -1) {
+          // if TTL is set to -1 the topology owner grants unlimited lifetime 
therefore no additional check is needed on lifespan
+          millis = lifetime;
+        } else if (lifetime <= tokenTTL) {
+          //this is expected due to security reasons: the configured TTL acts 
as an upper limit regardless of the supplied lifespan
           millis = lifetime;
         }
       }

Reply via email to