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;
}
}