Search in sources :

Example 11 with AccessToken

use of com.yahoo.athenz.auth.token.AccessToken in project athenz by yahoo.

the class ZTSClientTokenCacherTest method testZTSClientAccessTokenCacherInvalidPrincipal.

@Test
public void testZTSClientAccessTokenCacherInvalidPrincipal() {
    Principal principal = SimplePrincipal.create("user_domain", "user", "auth_creds", PRINCIPAL_AUTHORITY);
    ZTSRDLClientMock ztsClientMock = new ZTSRDLClientMock();
    ZTSClient client = new ZTSClient("http://localhost:4080", principal);
    client.setZTSRDLGeneratedClient(ztsClientMock);
    ZTSClient.ACCESS_TOKEN_CACHE.clear();
    AccessToken accessToken = createAccessToken("coretech", "athenz", null, null, null);
    PrivateKey privateKey = Crypto.loadPrivateKey(ecPrivateKey);
    String accessJws = accessToken.getSignedToken(privateKey, "eckey1", SignatureAlgorithm.ES256);
    assertNotNull(accessJws);
    AccessTokenResponse tokenResponse = new AccessTokenResponse();
    tokenResponse.setAccess_token(accessJws);
    tokenResponse.setExpires_in(3600);
    // invalid client id (athenz) without the service name will cause
    // the request to be skipped
    ZTSClientTokenCacher.setAccessToken(tokenResponse, null);
    assertEquals(ZTSClient.ACCESS_TOKEN_CACHE.size(), 0);
    client.close();
}
Also used : PrivateKey(java.security.PrivateKey) AccessToken(com.yahoo.athenz.auth.token.AccessToken) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal) Principal(com.yahoo.athenz.auth.Principal) Test(org.testng.annotations.Test)

Example 12 with AccessToken

use of com.yahoo.athenz.auth.token.AccessToken in project athenz by yahoo.

the class ZTSClientTokenCacherTest method createAccessToken.

AccessToken createAccessToken(final String audience, final String clientId, final String proxyPrincipal, final String authzDetails, final String proxyPrincipalsSpiffeUris) {
    AccessToken accessToken = new AccessToken();
    long now = System.currentTimeMillis();
    accessToken.setAuthTime(now);
    accessToken.setJwtId("jwt-id001");
    accessToken.setSubject("subject");
    accessToken.setUserId("userid");
    accessToken.setExpiryTime(now + 3600);
    accessToken.setIssueTime(now);
    accessToken.setClientId(clientId);
    accessToken.setAudience(audience);
    accessToken.setVersion(1);
    accessToken.setIssuer("athenz");
    accessToken.setProxyPrincipal(proxyPrincipal);
    accessToken.setAuthorizationDetails(authzDetails);
    if (proxyPrincipalsSpiffeUris != null) {
        List<String> uris = Stream.of(proxyPrincipalsSpiffeUris.split(",")).map(String::trim).collect(Collectors.toList());
        accessToken.setConfirmProxyPrincipalSpiffeUris(uris);
    }
    return accessToken;
}
Also used : AccessToken(com.yahoo.athenz.auth.token.AccessToken)

Example 13 with AccessToken

use of com.yahoo.athenz.auth.token.AccessToken in project athenz by yahoo.

the class ZTSClientTokenCacherTest method testZTSClientAccessTokenCacherWithIDToken.

@Test
public void testZTSClientAccessTokenCacherWithIDToken() {
    Principal principal = SimplePrincipal.create("user_domain", "user", "auth_creds", PRINCIPAL_AUTHORITY);
    ZTSRDLClientMock ztsClientMock = new ZTSRDLClientMock();
    ZTSClient client = new ZTSClient("http://localhost:4080", principal);
    client.setZTSRDLGeneratedClient(ztsClientMock);
    ZTSClient.ACCESS_TOKEN_CACHE.clear();
    final String authzDetails = "[{\"type\":\"message_access\",\"data\":\"resource\"}]";
    AccessToken accessToken = createAccessToken("coretech", "athenz.prod", "sports.proxy", authzDetails, null);
    PrivateKey privateKey = Crypto.loadPrivateKey(ecPrivateKey);
    String accessJws = accessToken.getSignedToken(privateKey, "eckey1", SignatureAlgorithm.ES256);
    assertNotNull(accessJws);
    AccessToken idToken = createAccessToken("coretech.api", "athenz.prod", null, null, null);
    String idJws = idToken.getSignedToken(privateKey, "eckey1", SignatureAlgorithm.ES256);
    assertNotNull(idJws);
    AccessTokenResponse tokenResponse = new AccessTokenResponse();
    tokenResponse.setAccess_token(accessJws);
    tokenResponse.setId_token(idJws);
    tokenResponse.setExpires_in(3600);
    List<String> roleNames = new ArrayList<>();
    roleNames.add("role1");
    roleNames.add("role2");
    ZTSClientTokenCacher.setAccessToken(tokenResponse, roleNames);
    assertEquals(ZTSClient.ACCESS_TOKEN_CACHE.size(), 1);
    final String cacheKey = ZTSClient.ACCESS_TOKEN_CACHE.keys().nextElement();
    final String clientKey = ZTSClient.getAccessTokenCacheKey("athenz", "prod", "coretech", roleNames, "api", "sports.proxy", authzDetails, null);
    assertEquals(cacheKey, clientKey);
    client.close();
}
Also used : PrivateKey(java.security.PrivateKey) AccessToken(com.yahoo.athenz.auth.token.AccessToken) ArrayList(java.util.ArrayList) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal) Principal(com.yahoo.athenz.auth.Principal) Test(org.testng.annotations.Test)

Example 14 with AccessToken

use of com.yahoo.athenz.auth.token.AccessToken in project athenz by yahoo.

the class ZTSClientTokenCacherTest method testZTSClientAccessTokenCacherWithProxyPrincipals.

@Test
public void testZTSClientAccessTokenCacherWithProxyPrincipals() {
    Principal principal = SimplePrincipal.create("user_domain", "user", "auth_creds", PRINCIPAL_AUTHORITY);
    ZTSRDLClientMock ztsClientMock = new ZTSRDLClientMock();
    ZTSClient client = new ZTSClient("http://localhost:4080", principal);
    client.setZTSRDLGeneratedClient(ztsClientMock);
    ZTSClient.ACCESS_TOKEN_CACHE.clear();
    final String proxyPrincipalsSpiffeUris = "spiffe://sports/sa/svc1,spiffe://weather/sa/svc2";
    AccessToken accessToken = createAccessToken("coretech", "athenz.prod", null, null, proxyPrincipalsSpiffeUris);
    PrivateKey privateKey = Crypto.loadPrivateKey(ecPrivateKey);
    String accessJws = accessToken.getSignedToken(privateKey, "eckey1", SignatureAlgorithm.ES256);
    assertNotNull(accessJws);
    AccessTokenResponse tokenResponse = new AccessTokenResponse();
    tokenResponse.setAccess_token(accessJws);
    tokenResponse.setExpires_in(3600);
    ZTSClientTokenCacher.setAccessToken(tokenResponse, null);
    assertEquals(ZTSClient.ACCESS_TOKEN_CACHE.size(), 1);
    final String cacheKey = ZTSClient.ACCESS_TOKEN_CACHE.keys().nextElement();
    final String clientKey = ZTSClient.getAccessTokenCacheKey("athenz", "prod", "coretech", null, null, null, null, proxyPrincipalsSpiffeUris);
    assertEquals(cacheKey, clientKey);
    client.close();
}
Also used : PrivateKey(java.security.PrivateKey) AccessToken(com.yahoo.athenz.auth.token.AccessToken) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal) Principal(com.yahoo.athenz.auth.Principal) Test(org.testng.annotations.Test)

Example 15 with AccessToken

use of com.yahoo.athenz.auth.token.AccessToken in project athenz by yahoo.

the class ZTSImpl method postAccessTokenRequest.

@Override
public AccessTokenResponse postAccessTokenRequest(ResourceContext ctx, String request) {
    final String caller = ctx.getApiName();
    final String principalDomain = logPrincipalAndGetDomain(ctx);
    validateRequest(ctx.request(), principalDomain, caller);
    // get our principal's name
    final Principal principal = ((RsrcCtxWrapper) ctx).principal();
    String principalName = principal.getFullName();
    if (StringUtil.isEmpty(request)) {
        throw requestError("Empty request body", caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN, principalDomain);
    }
    // we want to log the request body in our access log so
    // we know what is the client asking for but we'll just
    // limit the request up to 1K
    ctx.request().setAttribute(ACCESS_LOG_ADDL_QUERY, getQueryLogData(request));
    // decode and store the attributes that could exist in our
    // request body
    String grantType = null;
    String scope = null;
    String proxyForPrincipal = null;
    String authzDetails = null;
    List<String> proxyPrincipalsSpiffeUris = null;
    int expiryTime = 0;
    boolean useOpenIDIssuer = false;
    String[] comps = request.split("&");
    for (String comp : comps) {
        int idx = comp.indexOf('=');
        if (idx == -1) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("postAccessTokenRequest: skipping invalid component: {}", comp);
            }
            continue;
        }
        final String key = decodeString(comp.substring(0, idx));
        if (key == null) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("postAccessTokenRequest: skipping invalid component: {}", comp);
            }
            continue;
        }
        final String value = decodeString(comp.substring(idx + 1));
        if (value == null) {
            continue;
        }
        switch(key) {
            case KEY_GRANT_TYPE:
                grantType = value.toLowerCase();
                break;
            case KEY_SCOPE:
                scope = value.toLowerCase();
                break;
            case KEY_EXPIRES_IN:
                expiryTime = ZTSUtils.parseInt(value, 0);
                break;
            case KEY_PROXY_FOR_PRINCIPAL:
                proxyForPrincipal = getProxyForPrincipalValue(value.toLowerCase(), principalName, principalDomain, caller);
                break;
            case KEY_AUTHORIZATION_DETAILS:
                authzDetails = value;
                break;
            case KEY_PROXY_PRINCIPAL_SPIFFE_URIS:
                proxyPrincipalsSpiffeUris = getProxyPrincipalSpiffeUris(value.toLowerCase(), principalDomain, caller);
                break;
            case KEY_OPENID_ISSUER:
                useOpenIDIssuer = Boolean.parseBoolean(value);
                break;
        }
    }
    if (!OAUTH_GRANT_CREDENTIALS.equals(grantType)) {
        throw requestError("Invalid grant request: " + grantType, caller, principal.getDomain(), principalDomain);
    }
    if (scope == null || scope.isEmpty()) {
        throw requestError("Invalid request: no scope provided", caller, principal.getDomain(), principalDomain);
    }
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("postAccessTokenRequest(principal: {}, grant-type: {}, scope: {}, expires-in: {}, proxy-for-principal: {})", principalName, grantType, scope, expiryTime, proxyForPrincipal);
    }
    // our scopes are space separated list of values
    AccessTokenRequest tokenRequest = new AccessTokenRequest(scope);
    // before using any of our values let's validate that they
    // match our schema
    final String domainName = tokenRequest.getDomainName();
    setRequestDomain(ctx, domainName);
    validate(domainName, TYPE_DOMAIN_NAME, principalDomain, caller);
    String[] requestedRoles = tokenRequest.getRoleNames();
    if (requestedRoles != null) {
        for (String requestedRole : requestedRoles) {
            validate(requestedRole, TYPE_ENTITY_NAME, principalDomain, caller);
        }
    }
    // first retrieve our domain data object from the cache
    DataCache data = dataStore.getDataCache(domainName);
    if (data == null) {
        setRequestDomain(ctx, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
        throw notFoundError("No such domain: " + domainName, caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN, principalDomain);
    }
    // if we're given authorization details to be included in the
    // token then we must have only role requested and we need
    // to make sure the requested fields are valid according
    // to our configured authorization details entity for the role
    validateAuthorizationDetails(authzDetails, requestedRoles, data, caller, domainName, principalDomain);
    // check if the authorized service domain matches to the
    // requested domain name
    checkRoleTokenAuthorizedServiceRequest(principal, domainName, caller);
    // process our request and retrieve the roles for the principal
    Set<String> roles = new HashSet<>();
    dataStore.getAccessibleRoles(data, domainName, principalName, requestedRoles, roles, false);
    if (roles.isEmpty()) {
        throw forbiddenError(tokenErrorMessage(caller, principalName, domainName, requestedRoles), caller, domainName, principalDomain);
    }
    // if this is proxy for operation then we want to make sure that
    // both principals have access to the same set of roles so we'll
    // remove any roles that are authorized by only one of the principals
    String proxyUser = null;
    if (proxyForPrincipal != null) {
        if (tokenRequest.isOpenIdScope()) {
            throw requestError("Proxy Principal cannot request id tokens", caller, domainName, principalDomain);
        }
        // process the role lookup for the proxy principal
        Set<String> rolesForProxy = new HashSet<>();
        dataStore.getAccessibleRoles(data, domainName, proxyForPrincipal, requestedRoles, rolesForProxy, false);
        roles.retainAll(rolesForProxy);
        if (roles.isEmpty()) {
            throw forbiddenError(tokenErrorMessage(caller, proxyForPrincipal, domainName, requestedRoles), caller, domainName, principalDomain);
        }
        // we need to switch our principal and proxy for user
        proxyUser = principalName;
        principalName = proxyForPrincipal;
    }
    if (!isPrincipalRoleCertificateAccessValid(principal, domainName, roles)) {
        throw forbiddenError("Role based Principal does not include all roles", caller, domainName, principalDomain);
    }
    long tokenTimeout = determineTokenTimeout(data, roles, null, expiryTime);
    long iat = System.currentTimeMillis() / 1000;
    AccessToken accessToken = new AccessToken();
    accessToken.setVersion(1);
    accessToken.setJwtId(UUID.randomUUID().toString());
    accessToken.setAudience(domainName);
    accessToken.setClientId(principalName);
    accessToken.setIssueTime(iat);
    accessToken.setAuthTime(iat);
    accessToken.setExpiryTime(iat + tokenTimeout);
    accessToken.setUserId(principalName);
    accessToken.setSubject(principalName);
    accessToken.setIssuer(useOpenIDIssuer ? ztsOpenIDIssuer : ztsOAuthIssuer);
    accessToken.setProxyPrincipal(proxyUser);
    accessToken.setScope(new ArrayList<>(roles));
    accessToken.setAuthorizationDetails(authzDetails);
    // if we have a certificate used for mTLS authentication then
    // we're going to bind the certificate to the access token
    // and the optional proxy principals if specified
    X509Certificate cert = principal.getX509Certificate();
    if (cert != null) {
        accessToken.setConfirmX509CertHash(cert);
        if (proxyPrincipalsSpiffeUris != null) {
            accessToken.setConfirmProxyPrincipalSpiffeUris(proxyPrincipalsSpiffeUris);
        }
    }
    String accessJwts = accessToken.getSignedToken(privateKey.getKey(), privateKey.getId(), privateKey.getAlgorithm());
    // now let's check to see if we need to create openid token
    String idJwts = null;
    if (tokenRequest.isOpenIdScope()) {
        final String serviceName = tokenRequest.getServiceName();
        validate(serviceName, TYPE_SIMPLE_NAME, principalDomain, caller);
        IdToken idToken = new IdToken();
        idToken.setVersion(1);
        idToken.setAudience(tokenRequest.getDomainName() + "." + serviceName);
        idToken.setSubject(principalName);
        idToken.setIssuer(useOpenIDIssuer ? ztsOpenIDIssuer : ztsOAuthIssuer);
        // id tokens are only valid for up to 12 hours max
        // (value configured as a system property).
        // we'll use the user specified timeout unless it's
        // over the configured max
        idToken.setIssueTime(iat);
        idToken.setAuthTime(iat);
        idToken.setExpiryTime(iat + determineIdTokenTimeout(tokenTimeout));
        idJwts = idToken.getSignedToken(privateKey.getKey(), privateKey.getId(), privateKey.getAlgorithm());
    }
    AccessTokenResponse response = new AccessTokenResponse().setAccess_token(accessJwts).setToken_type(OAUTH_BEARER_TOKEN).setExpires_in((int) tokenTimeout).setId_token(idJwts);
    if (tokenRequest.sendScopeResponse() || requestedRoles != null && requestedRoles.length != roles.size()) {
        List<String> domainRoles = new ArrayList<>();
        for (String role : roles) {
            domainRoles.add(domainName + AccessTokenRequest.OBJECT_ROLE + role);
        }
        if (tokenRequest.isOpenIdScope()) {
            domainRoles.add(AccessTokenRequest.OBJECT_OPENID);
        }
        response.setScope(String.join(" ", domainRoles));
    }
    return response;
}
Also used : IdToken(com.yahoo.athenz.auth.token.IdToken) DataCache(com.yahoo.athenz.zts.cache.DataCache) X509Certificate(java.security.cert.X509Certificate) AccessToken(com.yahoo.athenz.auth.token.AccessToken) AccessTokenRequest(com.yahoo.athenz.zts.token.AccessTokenRequest) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal)

Aggregations

AccessToken (com.yahoo.athenz.auth.token.AccessToken)23 Test (org.testng.annotations.Test)12 PrivateKey (java.security.PrivateKey)10 SimplePrincipal (com.yahoo.athenz.auth.impl.SimplePrincipal)8 Principal (com.yahoo.athenz.auth.Principal)7 IOException (java.io.IOException)5 X509Certificate (java.security.cert.X509Certificate)4 ArrayList (java.util.ArrayList)4 Path (java.nio.file.Path)3 CryptoException (com.yahoo.athenz.auth.util.CryptoException)2 InvalidNameException (javax.naming.InvalidNameException)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 IdToken (com.yahoo.athenz.auth.token.IdToken)1 JwtsSigningKeyResolver (com.yahoo.athenz.auth.token.jwts.JwtsSigningKeyResolver)1 AccessCheckStatus (com.yahoo.athenz.zpe.AuthZpeClient.AccessCheckStatus)1 DataCache (com.yahoo.athenz.zts.cache.DataCache)1 AccessTokenRequest (com.yahoo.athenz.zts.token.AccessTokenRequest)1