Skip to content

Commit

Permalink
[fix][cli] Fix expiration of tokens created with "pulsar tokens creat…
Browse files Browse the repository at this point in the history
…e" (#22815)

Co-authored-by: David Jensen <djn@danskecommodities.com>
  • Loading branch information
entvex and David Jensen authored Jun 3, 2024
1 parent a6cee2b commit 245c3e8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import javax.crypto.SecretKey;
import lombok.Cleanup;
import org.apache.pulsar.broker.authentication.utils.AuthTokenUtils;
import org.apache.pulsar.cli.converters.picocli.TimeUnitToSecondsConverter;
import org.apache.pulsar.cli.converters.picocli.TimeUnitToMillisConverter;
import org.apache.pulsar.docs.tools.CmdGenerateDocs;
import picocli.CommandLine;
import picocli.CommandLine.Command;
Expand Down Expand Up @@ -128,7 +128,7 @@ public static class CommandCreateToken implements Callable<Integer> {
"--expiry-time"},
description = "Relative expiry time for the token (eg: 1h, 3d, 10y)."
+ " (m=minutes) Default: no expiration",
converter = TimeUnitToSecondsConverter.class)
converter = TimeUnitToMillisConverter.class)
private Long expiryTime = null;

@Option(names = {"-sk",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import picocli.CommandLine.Option;

Expand All @@ -36,6 +43,18 @@
*/
public class TokensCliUtilsTest {

@DataProvider(name = "desiredExpireTime")
public Object[][] desiredExpireTime() {
return new Object[][] {
{"600", 600}, //10m
{"5m", 300},
{"1h", 3600},
{"1d", 86400},
{"1w", 604800},
{"1y", 31536000}
};
}

@Test
public void testCreateToken() {
PrintStream oldStream = System.out;
Expand Down Expand Up @@ -75,6 +94,44 @@ public void testCreateToken() {
}
}

@Test(dataProvider = "desiredExpireTime")
public void commandCreateToken_WhenCreatingATokenWithExpiryTime_ShouldHaveTheDesiredExpireTime(String expireTime, int expireAsSec) throws Exception {
PrintStream oldStream = System.out;
try {
//Arrange
ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
System.setOut(new PrintStream(baoStream));

String[] command = {"create", "--secret-key",
"data:;base64,u+FxaxYWpsTfxeEmMh8fQeS3g2jfXw4+sGIv+PTY+BY=",
"--subject", "test",
"--expiry-time", expireTime,
};

new TokensCliUtils().execute(command);
String token = baoStream.toString();

Instant start = (new Date().toInstant().plus(expireAsSec - 5, ChronoUnit.SECONDS));
Instant stop = (new Date().toInstant().plus(expireAsSec + 5, ChronoUnit.SECONDS));

//Act
Claims jwt = Jwts.parserBuilder()
.setSigningKey(Decoders.BASE64.decode("u+FxaxYWpsTfxeEmMh8fQeS3g2jfXw4+sGIv+PTY+BY="))
.build()
.parseClaimsJws(token)
.getBody();

//Assert
//Checks if the token expires within +-5 sec.
assertTrue(( ! jwt.getExpiration().toInstant().isBefore( start ) ) && ( jwt.getExpiration().toInstant().isBefore( stop ) ));

} catch (Exception e) {
throw new RuntimeException(e);
} finally {
System.setOut(oldStream);
}
}

/**
* Test tokens generate docs.
*
Expand Down

0 comments on commit 245c3e8

Please sign in to comment.