Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KNOX-3020 - Introducing the 'type' metadata for Knox Tokens #881

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ public abstract class AbstractJWTFilter implements Filter {
*/
public static final String JWT_EXPECTED_SIGALG = "jwt.expected.sigalg";
public static final String JWT_DEFAULT_SIGALG = "RS256";
public static final String TYPE = "type";
public static final String CLIENT_ID = "CLIENT_ID";

static JWTMessages log = MessagesFactory.get( JWTMessages.class );

Expand Down Expand Up @@ -302,22 +300,16 @@ protected Subject createSubjectFromToken(final JWT token) throws UnknownTokenExc

public Subject createSubjectFromTokenIdentifier(final String tokenId) throws UnknownTokenException {
TokenMetadata metadata = tokenStateService.getTokenMetadata(tokenId);
String username = null;
if (metadata != null) {
String type = metadata.getMetadata(TYPE);
// using tokenID and passcode as CLIENT_ID and CLIENT_SECRET will
// result in a metadata item called "type". If the value is set
// to CLIENT_ID then it will be assumed to be a CLIENT_ID and we
// will use the token id as the username. Since we don't know the
// token id until it is created, the username is always the same
// in the record. Using the token id makes it a unique username for
// audit and the like.
if (CLIENT_ID.equalsIgnoreCase(type)) {
username = tokenId;
}
else {
username = metadata.getUserName();
}
final String username = metadata.isClientId() ? tokenId : metadata.getUserName();

return createSubjectFromTokenData(username, null);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ private void saveToken(JWT token) {
final long issueTime = System.currentTimeMillis();
tokenStateService.addToken(tokenId, issueTime, token.getExpiresDate().getTime(), tokenStateService.getDefaultMaxLifetimeDuration());
final TokenMetadata tokenMetadata = new TokenMetadata(token.getSubject());
tokenMetadata.setKnoxSsoCookie(true);
tokenMetadata.markKnoxSsoCookie();
tokenMetadata.useTokenNow();
tokenStateService.addMetadata(tokenId, tokenMetadata);
LOGGER.storedToken(getTopologyName(), Tokens.getTokenDisplayText(token.toString()), Tokens.getTokenIDDisplayText(tokenId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,7 @@ private void testLimitingTokensPerUser(int configuredLimit, int numberOfTokens,
final String tokenId = getTagValue(tokenResponse.getEntity().toString(), "token_id");
assertNotNull(tokenId);
final TokenMetadata tokenMetadata = new TokenMetadata(USER_NAME);
tokenMetadata.setKnoxSsoCookie(true);
tokenMetadata.markKnoxSsoCookie();
tss.addMetadata(tokenId, tokenMetadata);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public class TokenMetadata {
public static final String ENABLED = "enabled";
public static final String PASSCODE = "passcode";
public static final String CREATED_BY = "createdBy";
public static final String KNOX_SSO_COOKIE = "knoxSSOCookie";
public static final String LAST_USED_AT = "lastUsedAt";
private static final List<String> KNOWN_MD_NAMES = Arrays.asList(USER_NAME, COMMENT, ENABLED, PASSCODE, CREATED_BY, KNOX_SSO_COOKIE, LAST_USED_AT);
public static final String TYPE = "type";
smolnar82 marked this conversation as resolved.
Show resolved Hide resolved
private static final List<String> KNOWN_MD_NAMES = Arrays.asList(USER_NAME, COMMENT, ENABLED, PASSCODE, CREATED_BY, LAST_USED_AT, TYPE);

private final Map<String, String> metadataMap = new HashMap<>();

Expand All @@ -59,6 +59,7 @@ public TokenMetadata(String userName, String comment, boolean enabled) {
saveMetadata(USER_NAME, userName);
saveMetadata(COMMENT, comment);
setEnabled(enabled);
setType(TokenMetadataType.JWT);
}

private void saveMetadata(String key, String value) {
Expand Down Expand Up @@ -125,14 +126,6 @@ public String getCreatedBy() {
return getMetadata(CREATED_BY);
}

public void setKnoxSsoCookie(boolean knoxSsoCookie) {
saveMetadata(KNOX_SSO_COOKIE, String.valueOf(knoxSsoCookie));
}

public boolean isKnoxSsoCookie() {
return Boolean.parseBoolean(getMetadata(KNOX_SSO_COOKIE));
}

public void useTokenNow() {
saveMetadata(LAST_USED_AT, Instant.now().toString());
}
Expand All @@ -142,6 +135,28 @@ public Instant getLastUsedAt() {
return lastUsedAt == null ? null : Instant.parse(lastUsedAt);
}

public void setType(TokenMetadataType type) {
saveMetadata(TYPE, type.name());
}

public void markKnoxSsoCookie() {
setType(TokenMetadataType.KNOXSSO_COOKIE);
}

@JsonIgnore
public boolean isKnoxSsoCookie() {
return getType() == null ? false : TokenMetadataType.KNOXSSO_COOKIE == TokenMetadataType.valueOf(getType());
}

@JsonIgnore
public boolean isClientId() {
return getType() == null ? false : TokenMetadataType.CLIENT_ID == TokenMetadataType.valueOf(getType());
}

public String getType() {
return getMetadata(TYPE);
}

public String toJSON() {
return JsonUtils.renderAsJsonString(metadataMap);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.knox.gateway.services.security.token;

public enum TokenMetadataType {

JWT, KNOXSSO_COOKIE, CLIENT_ID;

}
2 changes: 1 addition & 1 deletion knox-token-management-ui/token-management/app/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class Metadata {
enabled: boolean;
userName: string;
createdBy: string;
knoxSsoCookie: boolean;
type: string;
comment: string;
customMetadataMap: Map<string, string>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,10 @@
</mat-cell>
</ng-container>

<ng-container matColumnDef="knoxSso">
<mat-header-cell *matHeaderCellDef mat-sort-header="knoxSso" style="text-align: center; justify-content: center;">KnoxSSO</mat-header-cell>
<ng-container matColumnDef="type">
<mat-header-cell *matHeaderCellDef mat-sort-header="type" style="text-align: center; justify-content: center;">Type</mat-header-cell>
<mat-cell *matCellDef="let knoxToken" style="text-align: center; justify-content: center;">
<img *ngIf="isKnoxSsoCookie(knoxToken)" src="assets/green_checkmark.svg" style="height:20px; width:auto" />
<img *ngIf="!isKnoxSsoCookie(knoxToken)" src="assets/red_cross_circle.svg" style="height:20px; width:auto" />
<img src="assets/{{knoxToken.metadata.type}}.png" style="height:30px; width:auto" />
</mat-cell>
</ng-container>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class TokenManagementComponent implements OnInit {
selection = new SelectionModel<KnoxToken>(true, []);
allKnoxTokens: KnoxToken[];

displayedColumns = ['select', 'tokenId', 'issued', 'expires', 'userName', 'impersonated', 'knoxSso', 'comment', 'metadata', 'actions'];
displayedColumns = ['select', 'tokenId', 'issued', 'expires', 'userName', 'impersonated', 'type', 'comment', 'metadata', 'actions'];
@ViewChild('knoxTokensPaginator') paginator: MatPaginator;
@ViewChild('knoxTokensSort') sort: MatSort = new MatSort();

Expand Down Expand Up @@ -130,7 +130,7 @@ export class TokenManagementComponent implements OnInit {
}

private isDisabledKnoxSsoCookie(token: KnoxToken): boolean {
return token.metadata.knoxSsoCookie && !token.metadata.enabled;
return this.isKnoxSsoCookie(token) && !token.metadata.enabled;
}

private updateTokens(tokens: KnoxToken[]): void {
Expand Down Expand Up @@ -217,7 +217,7 @@ export class TokenManagementComponent implements OnInit {
}

isKnoxSsoCookie(knoxToken: KnoxToken): boolean {
return knoxToken.metadata.knoxSsoCookie;
return 'KNOXSSO_COOKIE' === knoxToken.metadata.type;
}

isDisabledKnoxSSoCookie(knoxToken: KnoxToken): boolean {
Expand Down Expand Up @@ -269,7 +269,7 @@ export class TokenManagementComponent implements OnInit {
}

private selectionHasZeroKnoxSsoCookie(): boolean {
return this.selection.selected.every(token => !token.metadata.knoxSsoCookie);
return this.selection.selected.every(token => !this.isKnoxSsoCookie(token));
}

private selectionHasZeroExpiredToken(): boolean {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading