diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-09-27 14:25:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-27 14:25:05 +0200 |
commit | c4feaca0cfbf19b18c7b2ced33a1e18f80534b38 (patch) | |
tree | 87da93a1379ef5c2af1409c4a73e89c7668a42d6 | |
parent | d80ace95e5795ce6c937caf3912ef98e3ff3011e (diff) | |
parent | d84ed12d442cd2a50f1a1010a9972d64b76e23ba (diff) |
Merge pull request #19264 from vespa-engine/bjorncs/s3-athenz-access-control
Bjorncs/s3 athenz access control
17 files changed, 70 insertions, 24 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java index 970a70c6885..341b521212e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.aws; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.tenant.Tenant; import java.util.List; import java.util.Optional; @@ -12,7 +13,7 @@ import java.util.Optional; public class NoopRoleService implements RoleService { @Override - public Optional<TenantRoles> createTenantRole(TenantName tenant) { + public Optional<TenantRoles> createTenantRole(Tenant tenant) { return Optional.empty(); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java index d27fa0a5bd8..61007b9ff46 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.aws; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.tenant.Tenant; import java.util.List; import java.util.Optional; @@ -11,7 +12,7 @@ import java.util.Optional; */ public interface RoleService { - Optional<TenantRoles> createTenantRole(TenantName tenant); + Optional<TenantRoles> createTenantRole(Tenant tenant); /** Retrieve the names of the tenant roles (host and container). Does not guarantee these roles exist */ TenantRoles getTenantRole(TenantName tenant); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java index 7539ef3c63a..f650f71c0ec 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java @@ -8,6 +8,7 @@ import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.UpgradePolicy; import com.yahoo.config.provision.zone.ZoneApi; @@ -89,4 +90,7 @@ public interface ZoneRegistry { /** Returns a URL to the controller's api endpoint */ URI apiUrl(); + /** IAM tenant developer role ARN */ + Optional<String> tenantDeveloperRoleArn(TenantName tenant); + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java index 7fa46031c98..7fa46031c98 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java index 1060b118beb..1060b118beb 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java index cf6d73cb8f8..cf6d73cb8f8 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java index 15f2f97e7d1..15f2f97e7d1 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java index 80982d70107..80982d70107 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java index a20477d7aab..81c08e1083b 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java @@ -1,10 +1,6 @@ // Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.tenant; -import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; - -import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java index a12f351abd6..a12f351abd6 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java index a00dd626f0a..a00dd626f0a 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java index 9218bfcd850..9218bfcd850 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java index ca173437dd1..a7555307a59 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java @@ -33,8 +33,6 @@ public class CuratorArchiveBucketDb { * Policy size limit is 20kb, about 550 bytes for non-tenant related policies. Each tenant * needs about 500 + len(role_arn) bytes, we limit role_arn to 100 characters, so we can * fit about (20k - 550) / 600 ~ 32 tenants per bucket. - * - * This limit is only enforced for public systems as non-public systems does not use tenant specific policies. */ private final static int TENANTS_PER_BUCKET = 30; @@ -86,7 +84,7 @@ public class CuratorArchiveBucketDb { .orElseGet(() -> { // If not, find an existing bucket with space Optional<ArchiveBucket> unfilledBucket = zoneBuckets.stream() - .filter(bucket -> !system.isPublic() || bucket.tenants().size() < TENANTS_PER_BUCKET) + .filter(bucket -> bucket.tenants().size() < TENANTS_PER_BUCKET) .findAny(); // And place the tenant in that bucket. diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java index b096a853541..6c4f5ffff9d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java @@ -2,16 +2,25 @@ package com.yahoo.vespa.hosted.controller.maintenance; import com.google.common.collect.Maps; +import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.zone.ZoneApi; +import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.flags.BooleanFlag; +import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; import com.yahoo.vespa.hosted.controller.archive.CuratorArchiveBucketDb; +import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import java.time.Duration; +import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -27,6 +36,8 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { private final ArchiveService archiveService; private final ZoneRegistry zoneRegistry; private final Metric metric; + private final BooleanFlag archiveEnabled; + private final BooleanFlag developerRoleEnabled; public ArchiveAccessMaintainer(Controller controller, Metric metric, Duration interval) { super(controller, interval); @@ -34,6 +45,8 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { this.archiveService = controller.serviceRegistry().archiveService(); this.zoneRegistry = controller().zoneRegistry(); this.metric = metric; + this.archiveEnabled = Flags.ENABLE_ONPREM_TENANT_S3_ARCHIVE.bindTo(controller().flagSource()); + this.developerRoleEnabled = Flags.ENABLE_TENANT_DEVELOPER_ROLE.bindTo(controller().flagSource()); } @Override @@ -43,22 +56,45 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { metric.set(bucketCountMetricName, archiveBucketDb.buckets(zoneId).size(), metric.createContext(Map.of("zone", zoneId.value())))); - var tenantArchiveAccessRoles = controller().tenants().asList().stream() - .filter(t -> t instanceof CloudTenant) - .map(t -> (CloudTenant) t) - .filter(t -> t.archiveAccessRole().isPresent()) - .collect(Collectors.toUnmodifiableMap( - Tenant::name, cloudTenant -> cloudTenant.archiveAccessRole().orElseThrow())); - zoneRegistry.zones().controllerUpgraded().ids().forEach(zoneId -> - archiveBucketDb.buckets(zoneId).forEach(archiveBucket -> - archiveService.updateBucketAndKeyPolicy(zoneId, archiveBucket, - Maps.filterEntries(tenantArchiveAccessRoles, - entry -> archiveBucket.tenants().contains(entry.getKey()))) - ) + zoneRegistry.zones().controllerUpgraded().zones().forEach(z -> { + ZoneId zoneId = z.getId(); + var tenantArchiveAccessRoles = tenantArchiveAccessRoles(z); + archiveBucketDb.buckets(zoneId).forEach(archiveBucket -> + archiveService.updateBucketAndKeyPolicy(zoneId, archiveBucket, + Maps.filterEntries(tenantArchiveAccessRoles, + entry -> archiveBucket.tenants().contains(entry.getKey()))) + ); + } ); return 1.0; } + private Map<TenantName, String> tenantArchiveAccessRoles(ZoneApi zone) { + List<Tenant> tenants = controller().tenants().asList(); + if (zoneRegistry.system().isPublic()) { + return tenants.stream() + .filter(t -> t instanceof CloudTenant) + .map(t -> (CloudTenant) t) + .filter(t -> t.archiveAccessRole().isPresent()) + .collect(Collectors.toUnmodifiableMap( + Tenant::name, cloudTenant -> cloudTenant.archiveAccessRole().orElseThrow())); + } else { + return tenants.stream() + .filter(t -> t instanceof AthenzTenant + && enabled(archiveEnabled, t, zone) && enabled(developerRoleEnabled, t, zone)) + .map(Tenant::name) + .collect(Collectors.toUnmodifiableMap( + Function.identity(), t -> zoneRegistry.tenantDeveloperRoleArn(t).orElseThrow())); + + } + } + + private boolean enabled(BooleanFlag flag, Tenant tenant, ZoneApi zone) { + return flag.with(FetchVector.Dimension.TENANT_ID, tenant.name().value()) + .with(FetchVector.Dimension.ZONE_ID, zone.getId().value()) + .value(); + } + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java index ce6f9c802d6..d2b43dc63d9 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java @@ -27,9 +27,7 @@ public class TenantRoleMaintainer extends ControllerMaintainer { var tenants = controller().tenants().asList(); // Create separate athenz service for all tenants - tenants.stream() - .map(Tenant::name) - .forEach(roleService::createTenantRole); + tenants.forEach(roleService::createTenantRole); // Until we have moved to separate athenz service per tenant, make sure we update the shared policy // to allow ssh logins for hosts in prod/perf with a separate tenant iam role. diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java index fe03b69a3fe..7ce17aff782 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java @@ -9,6 +9,7 @@ import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.UpgradePolicy; import com.yahoo.config.provision.zone.ZoneApi; @@ -216,6 +217,8 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry return URI.create("https://api.tld:4443/"); } + @Override public Optional<String> tenantDeveloperRoleArn(TenantName tenant) { return Optional.empty(); } + @Override public boolean hasZone(ZoneId zoneId) { return zones.stream().anyMatch(zone -> zone.getId().equals(zoneId)); diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index c1ea44b7d46..28b031e5015 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -305,6 +305,15 @@ public class Flags { APPLICATION_ID ); + public static final UnboundBooleanFlag ENABLE_TENANT_DEVELOPER_ROLE = defineFeatureFlag( + "enable-tenant-developer-role", false, + List.of("bjorncs"), "2021-09-23", "2021-12-31", + "Enable tenant developer Athenz role in cd/main. Must be set on controller cluster only.", + "Takes effect immediately", + TENANT_ID + ); + + /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, List<String> owners, String createdAt, String expiresAt, String description, |