use of io.pravega.shared.security.token.JsonWebToken in project pravega by pravega.
the class AppendProcessor method setupAppend.
/**
* Setup an append so that subsequent append calls can occur.
* This requires validating that the segment exists.
* The reply: AppendSetup indicates that appends may proceed and contains the eventNumber which they should proceed
* from (in the event that this is a reconnect from a producer we have seen before)
*/
@Override
public void setupAppend(SetupAppend setupAppend) {
String newSegment = setupAppend.getSegment();
UUID writer = setupAppend.getWriterId();
log.info("Setting up appends for writer: {} on segment: {}", writer, newSegment);
if (this.tokenVerifier != null) {
try {
JsonWebToken token = tokenVerifier.verifyToken(newSegment, setupAppend.getDelegationToken(), AuthHandler.Permissions.READ_UPDATE);
setupTokenExpiryTask(setupAppend, token);
} catch (TokenException e) {
handleException(setupAppend.getWriterId(), setupAppend.getRequestId(), newSegment, "Update Segment Attribute", e);
return;
}
}
// Get the last Event Number for this writer from the Store. This operation (cache=true) will automatically put
// the value in the Store's cache so it's faster to access later.
AttributeId writerAttributeId = AttributeId.fromUUID(writer);
Futures.exceptionallyComposeExpecting(store.getAttributes(newSegment, Collections.singleton(writerAttributeId), true, TIMEOUT), e -> e instanceof StreamSegmentSealedException, () -> store.getAttributes(newSegment, Collections.singleton(writerAttributeId), false, TIMEOUT)).whenComplete((attributes, u) -> {
try {
if (u != null) {
handleException(writer, setupAppend.getRequestId(), newSegment, "setting up append", u);
} else {
// Last event number stored according to Segment store.
long eventNumber = attributes.getOrDefault(writerAttributeId, Attributes.NULL_ATTRIBUTE_VALUE);
// Create a new WriterState object based on the attribute value for the last event number for the writer.
// It should be noted that only one connection for a given segment writer is created by the client.
// The event number sent by the AppendSetup command is an implicit ack, the writer acks all events
// below the specified event number.
WriterState current = this.writerStates.put(Pair.of(newSegment, writer), new WriterState(eventNumber));
if (current != null) {
log.info("SetupAppend invoked again for writer {}. Last event number from store is {}. Prev writer state {}", writer, eventNumber, current);
}
connection.send(new AppendSetup(setupAppend.getRequestId(), newSegment, writer, eventNumber));
}
} catch (Throwable e) {
handleException(writer, setupAppend.getRequestId(), newSegment, "handling setupAppend result", e);
}
});
}
use of io.pravega.shared.security.token.JsonWebToken in project pravega by pravega.
the class GrpcAuthHelper method retrieveMasterToken.
/**
* Retrieves a master token for internal controller to segment store communication.
*
* @param tokenSigningKey Signing key for the JWT token.
* @return A new master token which has highest privileges.
*/
public static String retrieveMasterToken(String tokenSigningKey) {
Map<String, Object> customClaims = new HashMap<>();
customClaims.put("*", String.valueOf(READ_UPDATE));
return new JsonWebToken("segmentstoreresource", "segmentstore", tokenSigningKey.getBytes(), customClaims, null).toCompactString();
}
use of io.pravega.shared.security.token.JsonWebToken in project pravega by pravega.
the class AppendProcessorTest method testSetupTokenExpiryTaskClosesConnectionIfTokenHasExpired.
@Test
public void testSetupTokenExpiryTaskClosesConnectionIfTokenHasExpired() {
// Arrange
String streamSegmentName = "scope/stream/0.#epoch.0";
UUID clientId = UUID.randomUUID();
StreamSegmentStore mockStore = mock(StreamSegmentStore.class);
ServerConnection mockConnection = mock(ServerConnection.class);
@Cleanup("shutdown") ScheduledExecutorService executor = new InlineExecutor();
@Cleanup AppendProcessor processor = AppendProcessor.defaultBuilder().store(mockStore).connection(new TrackedConnection(mockConnection)).tokenExpiryHandlerExecutor(executor).build();
// Spy the actual Append Processor, so that we can have some of the methods return stubbed values.
AppendProcessor mockProcessor = spy(processor);
doReturn(true).when(mockProcessor).isSetupAppendCompleted(streamSegmentName, clientId);
JsonWebToken token = new JsonWebToken("subject", "audience", "secret".getBytes(), Date.from(Instant.now().minusSeconds(5)), null);
SetupAppend setupAppend = new SetupAppend(1, clientId, streamSegmentName, token.toCompactString());
// Act
mockProcessor.setupTokenExpiryTask(setupAppend, token).join();
// Assert
verify(mockConnection).close();
}
use of io.pravega.shared.security.token.JsonWebToken in project pravega by pravega.
the class AppendProcessorTest method testSetupTokenExpiryWhenConnectionSendThrowsException.
@Test
public void testSetupTokenExpiryWhenConnectionSendThrowsException() {
// Arrange
String streamSegmentName = "scope/stream/0.#epoch.0";
UUID clientId = UUID.randomUUID();
StreamSegmentStore mockStore = mock(StreamSegmentStore.class);
ServerConnection mockConnection = mock(ServerConnection.class);
@Cleanup("shutdown") ScheduledExecutorService executor = new InlineExecutor();
@Cleanup AppendProcessor processor = AppendProcessor.defaultBuilder().store(mockStore).connection(new TrackedConnection(mockConnection)).tokenExpiryHandlerExecutor(executor).build();
// Spy the actual Append Processor, so that we can have some of the methods return stubbed values.
AppendProcessor mockProcessor = spy(processor);
doReturn(true).when(mockProcessor).isSetupAppendCompleted(streamSegmentName, clientId);
doThrow(new RuntimeException()).when(mockConnection).send(any());
Date expiryDate = Date.from(Instant.now().plusMillis(300));
JsonWebToken token = new JsonWebToken("subject", "audience", "secret".getBytes(), expiryDate, null);
SetupAppend setupAppend = new SetupAppend(1, clientId, streamSegmentName, token.toCompactString());
// Act
mockProcessor.setupTokenExpiryTask(setupAppend, token).join();
}
Aggregations