summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorMorten Tokle <mortent@yahooinc.com>2023-11-07 13:45:25 +0100
committerMorten Tokle <mortent@yahooinc.com>2023-11-07 13:52:22 +0100
commit88f343b8fd3f6526933d1e975414424743bde728 (patch)
treebb8fc316a7eed67dcf5e21161e6e15ee2bef763f /vespa-athenz
parent8e983a117284a7e965e27e3a5c0a07cdbcb7d4cd (diff)
Support List of proxy principals in AthenzIdentityProvider
Diffstat (limited to 'vespa-athenz')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java9
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java9
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java53
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/LegacyAthenzIdentityProviderImpl.java5
4 files changed, 56 insertions, 20 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java
index 1a921c3b3ad..101d40be491 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java
@@ -141,16 +141,21 @@ public class DefaultZtsClient extends ClientBase implements ZtsClient {
}
@Override
- public AthenzAccessToken getAccessToken(AthenzDomain domain, List<AthenzIdentity> proxyPrincipals) {
+ public AthenzAccessToken getAccessToken(AthenzDomain domain, List<AthenzIdentity> proxyPrincipals) {
return this.getAccessTokenImpl(List.of(new AthenzResourceName(domain, "domain")), proxyPrincipals);
}
@Override
public AthenzAccessToken getAccessToken(List<AthenzRole> athenzRole) {
+ return getAccessToken(athenzRole, List.of());
+ }
+
+ @Override
+ public AthenzAccessToken getAccessToken(List<AthenzRole> athenzRole, List<AthenzIdentity> proxyPrincipals) {
List<AthenzResourceName> athenzResourceNames = athenzRole.stream()
.map(AthenzRole::toResourceName)
.toList();
- return this.getAccessTokenImpl(athenzResourceNames, List.of());
+ return this.getAccessTokenImpl(athenzResourceNames, proxyPrincipals);
}
private AthenzAccessToken getAccessTokenImpl(List<AthenzResourceName> resources, List<AthenzIdentity> proxyPrincipals) {
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
index 67a53715cec..0528042da16 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
@@ -129,6 +129,15 @@ public interface ZtsClient extends AutoCloseable {
AthenzAccessToken getAccessToken(List<AthenzRole> athenzRole);
/**
+ * Fetch an access token for the target roles
+ *
+ * @param athenzRole List of athenz roles to get access token for
+ * @param proxyPrincipals List of principals to allow proxying token
+ * @return An Athenz access token
+ */
+ AthenzAccessToken getAccessToken(List<AthenzRole> athenzRole, List<AthenzIdentity> proxyPrincipals);
+
+ /**
* Fetch role certificate for the target domain and role
*
* @param role Target role
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
index 623a8c856bc..a3916cbe080 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
@@ -20,6 +20,7 @@ import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.X509CertificateWithKey;
import com.yahoo.vespa.athenz.api.AthenzAccessToken;
import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.api.ZToken;
@@ -28,6 +29,7 @@ import com.yahoo.vespa.athenz.client.zts.ZtsClient;
import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider;
import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
import com.yahoo.vespa.athenz.tls.AthenzX509CertificateUtils;
+import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import com.yahoo.vespa.athenz.utils.SiaUtils;
import javax.net.ssl.SSLContext;
@@ -43,6 +45,7 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -89,8 +92,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
private final Map<AthenzRole, MutableX509KeyManager> roleKeyManagerCache;
private final LoadingCache<AthenzRole, ZToken> roleSpecificRoleTokenCache;
private final LoadingCache<AthenzDomain, ZToken> domainSpecificRoleTokenCache;
- private final LoadingCache<AthenzDomain, AthenzAccessToken> domainSpecificAccessTokenCache;
- private final LoadingCache<List<AthenzRole>, AthenzAccessToken> roleSpecificAccessTokenCache;
+ private final LoadingCache<AccessTokenCacheKey, AthenzAccessToken> accessTokenCache;
private final CsrGenerator csrGenerator;
@Inject
@@ -115,8 +117,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
this.roleKeyManagerCache = new HashMap<>();
this.roleSpecificRoleTokenCache = createCache(ROLE_TOKEN_EXPIRY, this::createRoleToken);
this.domainSpecificRoleTokenCache = createCache(ROLE_TOKEN_EXPIRY, this::createRoleToken);
- this.domainSpecificAccessTokenCache = createCache(ROLE_TOKEN_EXPIRY, this::createAccessToken);
- this.roleSpecificAccessTokenCache = createCache(ROLE_TOKEN_EXPIRY, this::createAccessToken);
+ this.accessTokenCache = createCache(ROLE_TOKEN_EXPIRY, this::createAccessToken);
this.csrGenerator = new CsrGenerator(config.athenzDnsSuffix(), config.configserverIdentityName());
this.autoReloadingX509KeyManager = autoReloadingX509KeyManager;
this.identitySslContext = createIdentitySslContext(autoReloadingX509KeyManager, trustStore);
@@ -221,7 +222,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
@Override
public String getAccessToken(String domain) {
try {
- return domainSpecificAccessTokenCache.get(new AthenzDomain(domain)).value();
+ return accessTokenCache.get(AccessTokenCacheKey.from(domain, List.of(), List.of())).value();
} catch (Exception e) {
throw new AthenzIdentityProviderException("Could not retrieve access token: " + e.getMessage(), e);
}
@@ -230,10 +231,16 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
@Override
public String getAccessToken(String domain, List<String> roles) {
try {
- List<AthenzRole> roleList = roles.stream()
- .map(roleName -> new AthenzRole(domain, roleName))
- .toList();
- return roleSpecificAccessTokenCache.get(roleList).value();
+ return accessTokenCache.get(AccessTokenCacheKey.from(domain, roles, List.of())).value();
+ } catch (Exception e) {
+ throw new AthenzIdentityProviderException("Could not retrieve access token: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public String getAccessToken(String domain, List<String> roles, List<String> proxyPrincipals) {
+ try {
+ return accessTokenCache.get(AccessTokenCacheKey.from(domain, roles, proxyPrincipals)).value();
} catch (Exception e) {
throw new AthenzIdentityProviderException("Could not retrieve access token: " + e.getMessage(), e);
}
@@ -305,15 +312,15 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
}
}
- private AthenzAccessToken createAccessToken(AthenzDomain domain) {
+ private AthenzAccessToken createAccessToken(AccessTokenCacheKey cacheKey) {
+ List<AthenzRole> roles = Optional.ofNullable(cacheKey.roles()).orElse(List.of());
+ List<AthenzIdentity> proxyPrincipals = Optional.ofNullable(cacheKey.proxyPrincipals()).orElse(List.of());
try (ZtsClient client = createZtsClient()) {
- return client.getAccessToken(domain);
- }
- }
-
- private AthenzAccessToken createAccessToken(List<AthenzRole> roles) {
- try (ZtsClient client = createZtsClient()) {
- return client.getAccessToken(roles);
+ if (roles.isEmpty()) {
+ return client.getAccessToken(cacheKey.domain(), proxyPrincipals);
+ } else {
+ return client.getAccessToken(roles, proxyPrincipals);
+ }
}
}
@@ -349,5 +356,15 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
log.log(Level.WARNING, "Failed to update metrics: " + t.getMessage(), t);
}
}
+ private record AccessTokenCacheKey(AthenzDomain domain, List<AthenzRole> roles, List<AthenzIdentity> proxyPrincipals) {
+ static AccessTokenCacheKey from(String domain, List<String> roles, List<String> proxyPrincipals) {
+ List<AthenzRole> roleList = Optional.ofNullable(roles).orElse(List.of()).stream()
+ .map(roleName -> new AthenzRole(domain, roleName))
+ .toList();
+ List<AthenzIdentity> proxyPrincipalList = Optional.ofNullable(proxyPrincipals).orElse(List.of()).stream()
+ .map(AthenzIdentities::from)
+ .toList();
+ return new AccessTokenCacheKey(new AthenzDomain(domain), roleList, proxyPrincipalList);
+ }
+ }
}
-
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/LegacyAthenzIdentityProviderImpl.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/LegacyAthenzIdentityProviderImpl.java
index 4058af31dde..7c375d4c0ff 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/LegacyAthenzIdentityProviderImpl.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/LegacyAthenzIdentityProviderImpl.java
@@ -261,6 +261,11 @@ public final class LegacyAthenzIdentityProviderImpl extends AbstractComponent im
}
@Override
+ public String getAccessToken(String domain, List<String> roles, List<String> proxyPrincipal) {
+ throw new UnsupportedOperationException("Not implemented in legacy client");
+ }
+
+ @Override
public PrivateKey getPrivateKey() {
return credentials.getKeyPair().getPrivate();
}