summaryrefslogtreecommitdiffstats
path: root/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
diff options
context:
space:
mode:
Diffstat (limited to 'vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java141
1 files changed, 141 insertions, 0 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
new file mode 100644
index 00000000000..ed9c1da56c2
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
@@ -0,0 +1,141 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.athenz.client.zms;
+
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzResourceName;
+import com.yahoo.vespa.athenz.api.AthenzRole;
+import com.yahoo.vespa.athenz.api.AthenzService;
+import com.yahoo.vespa.athenz.api.OktaAccessToken;
+import com.yahoo.vespa.athenz.client.common.ClientBase;
+import com.yahoo.vespa.athenz.client.zms.bindings.AccessResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.DomainListResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.MembershipResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.ProviderResourceGroupRolesRequestEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.TenancyRequestEntity;
+import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider;
+import org.apache.http.Header;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.message.BasicHeader;
+
+import javax.net.ssl.SSLContext;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author bjorncs
+ */
+public class DefaultZmsClient extends ClientBase implements ZmsClient {
+
+ private final URI zmsUrl;
+ private final AthenzIdentity identity;
+
+ public DefaultZmsClient(URI zmsUrl, AthenzIdentity identity, SSLContext sslContext) {
+ this(zmsUrl, identity, () -> sslContext);
+ }
+
+ public DefaultZmsClient(URI zmsUrl, ServiceIdentityProvider identityProvider) {
+ this(zmsUrl, identityProvider.identity(), identityProvider::getIdentitySslContext);
+ }
+
+ private DefaultZmsClient(URI zmsUrl, AthenzIdentity identity, Supplier<SSLContext> sslContextSupplier) {
+ super("vespa-zms-client", sslContextSupplier, ZmsClientException::new);
+ this.zmsUrl = addTrailingSlash(zmsUrl);
+ this.identity = identity;
+ }
+
+ private static URI addTrailingSlash(URI zmsUrl) {
+ return zmsUrl.getPath().endsWith("/") ? zmsUrl : URI.create(zmsUrl.toString() + '/');
+ }
+
+ @Override
+ public void createTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
+ HttpUriRequest request = RequestBuilder.put()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .setEntity(toJsonStringEntity(new TenancyRequestEntity(tenantDomain, providerService, Collections.emptyList())))
+ .build();
+ execute(request, response -> {
+ readEntity(response, String.class);
+ return response.getStatusLine().getStatusCode();
+ });
+ }
+
+ @Override
+ public void deleteTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
+ HttpUriRequest request = RequestBuilder.delete()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .build();
+ execute(request, response -> readEntity(response, String.class));
+ }
+
+ @Override
+ public void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, Set<RoleAction> roleActions, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
+ HttpUriRequest request = RequestBuilder.put()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .setEntity(toJsonStringEntity(new ProviderResourceGroupRolesRequestEntity(providerService, tenantDomain, roleActions, resourceGroup)))
+ .build();
+ execute(request, response -> readEntity(response, String.class)); // The ZMS API will return a json object that is similar to ProviderResourceGroupRolesRequestEntity
+ }
+
+ @Override
+ public void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
+ HttpUriRequest request = RequestBuilder.delete()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .build();
+ execute(request, response -> readEntity(response, String.class));
+ }
+
+ @Override
+ public boolean getMembership(AthenzRole role, AthenzIdentity identity) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s/member/%s", role.domain().getName(), role.roleName(), identity.getFullName()));
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(uri)
+ .build();
+ return execute(request, response -> {
+ MembershipResponseEntity membership = readEntity(response, MembershipResponseEntity.class);
+ return membership.isMember;
+ });
+ }
+
+ @Override
+ public List<AthenzDomain> getDomainList(String prefix) {
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(zmsUrl.resolve("domain"))
+ .addParameter("prefix", prefix)
+ .build();
+ return execute(request, response -> {
+ DomainListResponseEntity result = readEntity(response, DomainListResponseEntity.class);
+ return result.domains.stream().map(AthenzDomain::new).collect(toList());
+ });
+ }
+
+ @Override
+ public boolean hasAccess(AthenzResourceName resource, String action, AthenzIdentity identity) {
+ URI uri = zmsUrl.resolve(String.format("access/%s/%s", action, resource.toResourceNameString()));
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(uri)
+ .build();
+ return execute(request, response -> {
+ AccessResponseEntity result = readEntity(response, AccessResponseEntity.class);
+ return result.granted;
+ });
+ }
+
+ private static Header creatOktaAccessTokenHeader(OktaAccessToken token) {
+ return new BasicHeader("Cookie", String.format("okta_at=%s", token.token()));
+ }
+}