Skip to content

Commit

Permalink
Domain Dependency for Tenancy
Browse files Browse the repository at this point in the history
Signed-off-by: Ofer Levi <[email protected]>
  • Loading branch information
OferLevi85 committed Feb 20, 2022
1 parent f422912 commit 2eed716
Show file tree
Hide file tree
Showing 4 changed files with 769 additions and 89 deletions.
8 changes: 8 additions & 0 deletions servers/zms/src/main/java/com/yahoo/athenz/zms/DBService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4351,6 +4351,14 @@ void executePutTenantRoles(ResourceContext ctx, String provSvcDomain, String pro

checkDomainAuditEnabled(con, provSvcDomain, auditRef, caller, principalName, AUDIT_TYPE_TENANCY);

// verify tenant domain exists

Domain domain = con.getDomain(tenantDomain);
if (domain == null) {
con.rollbackChanges();
throw ZMSUtils.notFoundError(caller + ": Unknown tenant domain: " + tenantDomain, caller);
}

String trustedRolePrefix = ZMSUtils.getTrustedResourceGroupRolePrefix(provSvcDomain,
provSvcName, tenantDomain, resourceGroup);

Expand Down
115 changes: 103 additions & 12 deletions servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6726,6 +6726,49 @@ public void putTenancy(ResourceContext ctx, String tenantDomain, String provider
if (authzServiceTokenOperation) {
setupTenantAdminPolicyInProvider(ctx, provSvcDomain, provSvcName, tenantDomain,
false, auditRef, caller);

// If listed as service provider, register dependency between the provider service and the tenant domain (unless dependency exist
// following creation of a previous resource group)

tenancyRegisterDomainDependency(ctx, tenantDomain, provider, true, auditRef, caller);
}
}

private void tenancyRegisterDomainDependency(ResourceContext ctx, String tenantDomain, String provider, boolean authzServiceTokenOperation, String auditRef, String caller) {
String serviceToRegister = provider;
try {
serviceToRegister = getAuthorizedProviderService((RsrcCtxWrapper) ctx, serviceToRegister, authzServiceTokenOperation, caller);
if (serviceProviderManager.isServiceProvider(serviceToRegister)) {

DomainList domainList = dbService.listDomainDependencies(serviceToRegister);
if (!domainList.getNames().contains(tenantDomain)) {
dbService.putDomainDependency(ctx, tenantDomain, serviceToRegister, auditRef, caller);
}
}
} catch (ResourceException ex) {
if (ex.getCode() == ResourceException.UNAUTHORIZED) {
LOG.warn("Not registering domain dependency: " + ex.getMessage());
return;
}
throw ex;
}
}

private void tenancyDeregisterDomainDependency(ResourceContext ctx, String tenantDomain, String provSvcDomain, String provSvcName, boolean authzServiceTokenOperation, String auditRef, String caller) {
String serviceToDeregister = provSvcDomain + "." + provSvcName;
try {
serviceToDeregister = getAuthorizedProviderService((RsrcCtxWrapper) ctx, serviceToDeregister, authzServiceTokenOperation, caller);
if (serviceProviderManager.isServiceProvider(serviceToDeregister)) {
boolean tenantDomainRolesExist = isTenantDomainRolesExist(tenantDomain, provSvcDomain, provSvcName);
if (!tenantDomainRolesExist) {
dbService.deleteDomainDependency(ctx, tenantDomain, serviceToDeregister, auditRef, caller);
}
}
} catch (ResourceException ex) {
if (ex.getCode() == ResourceException.UNAUTHORIZED) {
return;
}
throw ex;
}
}

Expand Down Expand Up @@ -6776,6 +6819,10 @@ public void deleteTenancy(ResourceContext ctx, String tenantDomain, String provi
if (authzServiceTokenOperation) {
dbService.executeDeleteTenantRoles(ctx, provSvcDomain, provSvcName, tenantDomain, null,
auditRef, caller);

// If listed as service provider, check if there are remaining resource group roles. If not - de-register dependency between the provider service and the tenant domain

tenancyDeregisterDomainDependency(ctx, tenantDomain, provSvcDomain, provSvcName, true, auditRef, caller);
}

// now clean-up local domain roles and policies for this tenant
Expand Down Expand Up @@ -6834,6 +6881,11 @@ public void putTenant(ResourceContext ctx, String providerDomain, String provide

setupTenantAdminPolicyInProvider(ctx, providerDomain, providerService, tenantDomain,
false, auditRef, caller);

// If listed as service provider, register dependency between the provider service and the tenant domain (unless dependency exist
// following creation of a previous resource group)
String provider = providerDomain + "." + providerService;
tenancyRegisterDomainDependency(ctx, tenantDomain, provider, false, auditRef, caller);
}

@Override
Expand Down Expand Up @@ -6872,6 +6924,10 @@ public void deleteTenant(ResourceContext ctx, String providerDomain, String prov

dbService.executeDeleteTenantRoles(ctx, providerDomain, providerService, tenantDomain,
null, auditRef, caller);

// If listed as service provider, check if there are remaining resource group roles. If not - de-register dependency between the provider service and the tenant domain

tenancyDeregisterDomainDependency(ctx, tenantDomain, providerDomain, providerService, false, auditRef, caller);
}

boolean validateTenancyObject(Tenancy tenant, final String tenantDomain, final String providerService) {
Expand Down Expand Up @@ -6991,6 +7047,13 @@ public TenantResourceGroupRoles putTenantResourceGroupRoles(ResourceContext ctx,

dbService.executePutTenantRoles(ctx, provSvcDomain, provSvcName, tenantDomain,
resourceGroup, detail.getRoles(), false, auditRef, caller);

// If listed as service provider, register dependency between the provider service and the tenant domain (unless dependency exist
// following creation of a previous resource group)

String provider = provSvcDomain + "." + provSvcName;
tenancyRegisterDomainDependency(ctx, tenantDomain, provider, false, auditRef, caller);

return detail;
}

Expand Down Expand Up @@ -7303,9 +7366,25 @@ public void deleteProviderResourceGroupRoles(ResourceContext ctx, String tenantD

dbService.executeDeleteTenantRoles(ctx, provSvcDomain, provSvcName, tenantDomain,
resourceGroup, auditRef, caller);

// If listed as service provider, check if there are remaining resource group roles. If not - de-register dependency between the provider service and the tenant domain

tenancyDeregisterDomainDependency(ctx, tenantDomain, provSvcDomain, provSvcName, true, auditRef, caller);
}
}

private boolean isTenantDomainRolesExist(String tenantDomain, String provSvcDomain, String provSvcName) {
final String rolePrefix = ZMSUtils.getTenantResourceGroupRolePrefix(provSvcName, tenantDomain, null);
// find roles matching the prefix

List<String> tenantDomainRoles = dbService.listRoles(provSvcDomain);
boolean tenantDomainRolesExist = tenantDomainRoles.stream()
.filter(role -> dbService.isTenantRolePrefixMatch(role, rolePrefix, null, tenantDomain))
.findAny()
.isPresent();
return tenantDomainRolesExist;
}

public ProviderResourceGroupRoles getProviderResourceGroupRoles(ResourceContext ctx, String tenantDomain,
String provSvcDomain, String provSvcName, String resourceGroup) {

Expand Down Expand Up @@ -7492,6 +7571,11 @@ public ProviderResourceGroupRoles putProviderResourceGroupRoles(ResourceContext

dbService.executePutTenantRoles(ctx, provSvcDomain, provSvcName, tenantDomain,
resourceGroup, roleActions, false, auditRef, caller);

// If listed as service provider, register dependency between the provider service and the tenant domain (unless dependency exist
// following creation of a previous resource group)

tenancyRegisterDomainDependency(ctx, tenantDomain, authorizedService, true, auditRef, caller);
}

return detail;
Expand Down Expand Up @@ -7630,6 +7714,10 @@ public void deleteTenantResourceGroupRoles(ResourceContext ctx, String provSvcDo

dbService.executeDeleteTenantRoles(ctx, provSvcDomain, provSvcName, tenantDomain,
resourceGroup, auditRef, caller);

// If listed as service provider, check if there are remaining resource group roles. If not - de-register dependency between the provider service and the tenant domain

tenancyDeregisterDomainDependency(ctx, tenantDomain, provSvcDomain, provSvcName, false, auditRef, caller);
}

void validateRequest(HttpServletRequest request, String caller) {
Expand Down Expand Up @@ -10206,7 +10294,7 @@ public void putDomainDependency(ResourceContext ctx, String domainName, String a
}

String service = (dependentService != null) ? dependentService.getService() : null;
service = getAuthorizedProviderService((RsrcCtxWrapper) ctx, service, caller);
service = getAuthorizedProviderService((RsrcCtxWrapper) ctx, service, false, caller);

validateRequest(ctx.request(), caller);

Expand All @@ -10233,7 +10321,7 @@ public void deleteDomainDependency(ResourceContext ctx, String domainName, Strin
throw ZMSUtils.requestError(SERVER_READ_ONLY_MESSAGE, caller);
}

service = getAuthorizedProviderService((RsrcCtxWrapper) ctx, service, caller);
service = getAuthorizedProviderService((RsrcCtxWrapper) ctx, service, false, caller);

validateRequest(ctx.request(), caller);

Expand All @@ -10251,18 +10339,21 @@ public void deleteDomainDependency(ResourceContext ctx, String domainName, Strin
dbService.deleteDomainDependency(ctx, domainName, service, auditRef, caller);
}

String getAuthorizedProviderService(RsrcCtxWrapper ctx, String service, String caller) {
// If system administrator - service is mandatory
// Otherwise ignore it and use the principal as dependent service
String getAuthorizedProviderService(RsrcCtxWrapper ctx, String service, boolean authzServiceTokenOperation, String caller) {

if (!authzServiceTokenOperation) {
// If system administrator - service is mandatory
// Otherwise ignore it and use the principal as dependent service

Principal principal = ctx.principal();
boolean isSysAdminUser = isSysAdminUser(principal, false);
if (isSysAdminUser) {
if (StringUtil.isEmpty(service)) {
throw ZMSUtils.requestError("service is mandatory", caller);
Principal principal = ctx.principal();
boolean isSysAdminUser = isSysAdminUser(principal, false);
if (isSysAdminUser) {
if (StringUtil.isEmpty(service)) {
throw ZMSUtils.requestError("service is mandatory", caller);
}
} else {
service = principal.getFullName();
}
} else {
service = principal.getFullName();
}
service = service.toLowerCase();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ public void testGetAuthorizedProviderService() {
// Throw failure for service which is not a service provider

try {
zmsImpl.getAuthorizedProviderService(regularUserCtx, null, caller);
zmsImpl.getAuthorizedProviderService(regularUserCtx, null, false, caller);
} catch (ResourceException ex) {
assertEquals(ex.getMessage(), "ResourceException (401): {code: 401, message: \"user.user1 is not an authorized service provider\"}");
}
Expand All @@ -465,15 +465,15 @@ public void testGetAuthorizedProviderService() {

RsrcCtxWrapper sysAdminCtx = zmsTestInitializer.contextWithMockPrincipal(caller);
try {
zmsImpl.getAuthorizedProviderService(sysAdminCtx, null, caller);
zmsImpl.getAuthorizedProviderService(sysAdminCtx, null, false, caller);
} catch (ResourceException ex) {
assertEquals(ex.getMessage(), "ResourceException (400): {code: 400, message: \"service is mandatory\"}");
}

// Throw failure for system administrator that specified a non service-provider service

try {
zmsImpl.getAuthorizedProviderService(sysAdminCtx, "not.service.provider", caller);
zmsImpl.getAuthorizedProviderService(sysAdminCtx, "not.service.provider", false, caller);
} catch (ResourceException ex) {
assertEquals(ex.getMessage(), "ResourceException (401): {code: 401, message: \"not.service.provider is not an authorized service provider\"}");
}
Expand All @@ -485,23 +485,29 @@ public void testGetAuthorizedProviderService() {
// For non system administrators - trying to specify the service provider isn't enough, principal must be the service provider

try {
zmsImpl.getAuthorizedProviderService(regularUserCtx, "service.provider", caller);
zmsImpl.getAuthorizedProviderService(regularUserCtx, "service.provider", false, caller);
} catch (ResourceException ex) {
assertEquals(ex.getMessage(), "ResourceException (401): {code: 401, message: \"user.user1 is not an authorized service provider\"}");
}

// Successful for system administrator or the service provider itself

String authorizedProviderService = zmsImpl.getAuthorizedProviderService(sysAdminCtx, "service.provider", caller);
String authorizedProviderService = zmsImpl.getAuthorizedProviderService(sysAdminCtx, "service.provider", false, caller);
assertEquals(authorizedProviderService, "service.provider");
RsrcCtxWrapper serviceProviderCtx = zmsTestInitializer.contextWithMockPrincipal(caller, "service", "provider");
authorizedProviderService = zmsImpl.getAuthorizedProviderService(serviceProviderCtx, "service.provider", caller);
authorizedProviderService = zmsImpl.getAuthorizedProviderService(serviceProviderCtx, "service.provider", false, caller);
assertEquals(authorizedProviderService, "service.provider");

// Also Successful for system administrator that isn't human
// Successful for system administrator that isn't human

RsrcCtxWrapper serviceSysAdminCtx = zmsTestInitializer.generateServiceSysAdmin(caller, "admindomain", "serviceprincipal");
authorizedProviderService = zmsImpl.getAuthorizedProviderService(serviceSysAdminCtx, "service.provider", caller);
authorizedProviderService = zmsImpl.getAuthorizedProviderService(serviceSysAdminCtx, "service.provider", false, caller);
assertEquals(authorizedProviderService, "service.provider");

// Successful for request with authorized service token

RsrcCtxWrapper nonServiceProviderCtx = zmsTestInitializer.contextWithMockPrincipal(caller, "service", "not-provider");
authorizedProviderService = zmsImpl.getAuthorizedProviderService(nonServiceProviderCtx, "service.provider", true, caller);
assertEquals(authorizedProviderService, "service.provider");
}
}
Loading

0 comments on commit 2eed716

Please sign in to comment.