/* * Copyright © 2014 Cask Data, Inc. * * Licensed 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 co.cask.cdap.security.auth; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.common.io.Codec; import co.cask.cdap.common.utils.ImmutablePair; import com.google.common.collect.Lists; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * Tests related to {@link TokenManager} implementations. */ public abstract class TestTokenManager { protected static final Logger LOG = LoggerFactory.getLogger(TestTokenManager.class); protected static final long TOKEN_DURATION = 3600 * 1000; protected abstract ImmutablePair<TokenManager, Codec<AccessToken>> getTokenManagerAndCodec(); @Test public void testTokenValidation() throws Exception { ImmutablePair<TokenManager, Codec<AccessToken>> pair = getTokenManagerAndCodec(); TokenManager tokenManager = pair.getFirst(); tokenManager.startAndWait(); Codec<AccessToken> tokenCodec = pair.getSecond(); long now = System.currentTimeMillis(); String user = "testuser"; List<String> groups = Lists.newArrayList("users", "admins"); AccessTokenIdentifier ident1 = new AccessTokenIdentifier(user, groups, now, now + TOKEN_DURATION); AccessToken token1 = tokenManager.signIdentifier(ident1); LOG.info("Signed token is: " + Bytes.toStringBinary(tokenCodec.encode(token1))); // should be valid since we just signed it tokenManager.validateSecret(token1); // test token expiration AccessTokenIdentifier expiredIdent = new AccessTokenIdentifier(user, groups, now - 1000, now - 1); AccessToken expiredToken = tokenManager.signIdentifier(expiredIdent); try { tokenManager.validateSecret(expiredToken); fail("Token should have been expired but passed validation: " + Bytes.toStringBinary(tokenCodec.encode(expiredToken))); } catch (InvalidTokenException expected) { } // test token with invalid signature Random random = new Random(); byte[] invalidDigest = token1.getDigestBytes(); random.nextBytes(invalidDigest); AccessToken invalidToken = new AccessToken(token1.getIdentifier(), token1.getKeyId(), invalidDigest); try { tokenManager.validateSecret(invalidToken); fail("Token should have been rejected for invalid digest but passed: " + Bytes.toStringBinary(tokenCodec.encode(invalidToken))); } catch (InvalidTokenException expected) { } // test token with bad key ID AccessToken invalidKeyToken = new AccessToken(token1.getIdentifier(), token1.getKeyId() + 1, token1.getDigestBytes()); try { tokenManager.validateSecret(invalidKeyToken); fail("Token should have been rejected for invalid key ID but passed: " + Bytes.toStringBinary(tokenCodec.encode(invalidToken))); } catch (InvalidTokenException expected) { } tokenManager.stopAndWait(); } @Test public void testTokenSerialization() throws Exception { ImmutablePair<TokenManager, Codec<AccessToken>> pair = getTokenManagerAndCodec(); TokenManager tokenManager = pair.getFirst(); tokenManager.startAndWait(); Codec<AccessToken> tokenCodec = pair.getSecond(); long now = System.currentTimeMillis(); String user = "testuser"; List<String> groups = Lists.newArrayList("users", "admins"); AccessTokenIdentifier ident1 = new AccessTokenIdentifier(user, groups, now, now + TOKEN_DURATION); AccessToken token1 = tokenManager.signIdentifier(ident1); byte[] tokenBytes = tokenCodec.encode(token1); AccessToken token2 = tokenCodec.decode(tokenBytes); assertEquals(token1, token2); LOG.info("Deserialized token is: " + Bytes.toStringBinary(tokenCodec.encode(token2))); // should be valid since we just signed it tokenManager.validateSecret(token2); tokenManager.stopAndWait(); } }