diff options
author | Øyvind Grønnesby <oyving@yahooinc.com> | 2022-12-13 13:04:42 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@yahooinc.com> | 2022-12-13 13:44:26 +0100 |
commit | f8fbe68bd0dc76c6447e6abbfc4cffd4080150ab (patch) | |
tree | e2f830bf20054629722d9b2253d074d2feea168d | |
parent | 1d0045f5e0389cbaa3115293fddbe1fd4a87a82d (diff) |
Add timestamp for last role maintenance run
11 files changed, 92 insertions, 42 deletions
diff --git a/controller-api/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 79ab8654aa4..53a3f431de7 100644 --- a/controller-api/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 @@ -27,8 +27,8 @@ public class AthenzTenant extends Tenant { * Use {@link #create(TenantName, AthenzDomain, Property, Optional, Instant)}. * */ public AthenzTenant(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, - Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo) { - super(name, createdAt, lastLoginInfo, contact); + Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo, Instant tenantRolesLastMaintained) { + super(name, createdAt, lastLoginInfo, contact, tenantRolesLastMaintained); this.domain = Objects.requireNonNull(domain, "domain must be non-null"); this.property = Objects.requireNonNull(property, "property must be non-null"); this.propertyId = Objects.requireNonNull(propertyId, "propertyId must be non-null"); @@ -62,7 +62,7 @@ public class AthenzTenant extends Tenant { /** Create a new Athenz tenant */ public static AthenzTenant create(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, Instant createdAt) { - return new AthenzTenant(requireName(name), domain, property, propertyId, Optional.empty(), createdAt, LastLoginInfo.EMPTY); + return new AthenzTenant(requireName(name), domain, property, propertyId, Optional.empty(), createdAt, LastLoginInfo.EMPTY, Instant.EPOCH); } @Override diff --git a/controller-api/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 ae0467fcc86..2275f3a9bf8 100644 --- a/controller-api/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 @@ -31,8 +31,8 @@ public class CloudTenant extends Tenant { /** Public for the serialization layer — do not use! */ public CloudTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<SimplePrincipal> creator, BiMap<PublicKey, SimplePrincipal> developerKeys, TenantInfo info, - List<TenantSecretStore> tenantSecretStores, ArchiveAccess archiveAccess, Optional<Instant> invalidateUserSessionsBefore) { - super(name, createdAt, lastLoginInfo, Optional.empty()); + List<TenantSecretStore> tenantSecretStores, ArchiveAccess archiveAccess, Optional<Instant> invalidateUserSessionsBefore, Instant tenantRoleLastMaintained) { + super(name, createdAt, lastLoginInfo, Optional.empty(), tenantRoleLastMaintained); this.creator = creator; this.developerKeys = developerKeys; this.info = Objects.requireNonNull(info); @@ -47,7 +47,7 @@ public class CloudTenant extends Tenant { createdAt, LastLoginInfo.EMPTY, Optional.ofNullable(creator).map(SimplePrincipal::of), - ImmutableBiMap.of(), TenantInfo.empty(), List.of(), new ArchiveAccess(), Optional.empty()); + ImmutableBiMap.of(), TenantInfo.empty(), List.of(), new ArchiveAccess(), Optional.empty(), Instant.EPOCH); } /** The user that created the tenant */ diff --git a/controller-api/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..b58fdf81278 100644 --- a/controller-api/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 @@ -17,7 +17,7 @@ public class DeletedTenant extends Tenant { private final Instant deletedAt; public DeletedTenant(TenantName name, Instant createdAt, Instant deletedAt) { - super(name, createdAt, LastLoginInfo.EMPTY, Optional.empty()); + super(name, createdAt, LastLoginInfo.EMPTY, Optional.empty(), Instant.EPOCH); this.deletedAt = Objects.requireNonNull(deletedAt, "deletedAt must be non-null"); } diff --git a/controller-api/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 ed7e6827516..a4500991bf2 100644 --- a/controller-api/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 @@ -19,12 +19,14 @@ public abstract class Tenant { private final Instant createdAt; private final LastLoginInfo lastLoginInfo; private final Optional<Contact> contact; + private final Instant tenantRolesLastMaintained; - Tenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Contact> contact) { + Tenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Contact> contact, Instant tenantRolesLastMaintained) { this.name = name; this.createdAt = createdAt; this.lastLoginInfo = lastLoginInfo; this.contact = contact; + this.tenantRolesLastMaintained = tenantRolesLastMaintained; } /** Name of this tenant */ @@ -47,6 +49,10 @@ public abstract class Tenant { return contact; } + public Instant tenantRolesLastMaintained() { + return tenantRolesLastMaintained; + } + public abstract Type type(); @Override diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java index da40f63d543..f8135e27d74 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java @@ -41,11 +41,13 @@ public abstract class LockedTenant { final TenantName name; final Instant createdAt; final LastLoginInfo lastLoginInfo; + final Instant tenantRolesLastMaintained; - private LockedTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo) { + private LockedTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Instant tenantRolesLastMaintained) { this.name = requireNonNull(name); this.createdAt = requireNonNull(createdAt); this.lastLoginInfo = requireNonNull(lastLoginInfo); + this.tenantRolesLastMaintained = requireNonNull(tenantRolesLastMaintained); } static LockedTenant of(Tenant tenant, Mutex lock) { @@ -62,6 +64,8 @@ public abstract class LockedTenant { public abstract LockedTenant with(LastLoginInfo lastLoginInfo); + public abstract LockedTenant with(Instant tenantRolesLastMaintained); + public Deleted deleted(Instant deletedAt) { return new Deleted(new DeletedTenant(name, createdAt, deletedAt)); } @@ -81,8 +85,8 @@ public abstract class LockedTenant { private final Optional<Contact> contact; private Athenz(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, - Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo) { - super(name, createdAt, lastLoginInfo); + Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo, Instant tenantRolesLastMaintained) { + super(name, createdAt, lastLoginInfo, tenantRolesLastMaintained); this.domain = domain; this.property = property; this.propertyId = propertyId; @@ -90,33 +94,38 @@ public abstract class LockedTenant { } private Athenz(AthenzTenant tenant) { - this(tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact(), tenant.createdAt(), tenant.lastLoginInfo()); + this(tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact(), tenant.createdAt(), tenant.lastLoginInfo(), tenant.tenantRolesLastMaintained()); } @Override public AthenzTenant get() { - return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); + return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } public Athenz with(AthenzDomain domain) { - return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } public Athenz with(Property property) { - return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } public Athenz with(PropertyId propertyId) { - return new Athenz(name, domain, property, Optional.of(propertyId), contact, createdAt, lastLoginInfo); + return new Athenz(name, domain, property, Optional.of(propertyId), contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } public Athenz with(Contact contact) { - return new Athenz(name, domain, property, propertyId, Optional.of(contact), createdAt, lastLoginInfo); + return new Athenz(name, domain, property, propertyId, Optional.of(contact), createdAt, lastLoginInfo, tenantRolesLastMaintained); } @Override public LockedTenant with(LastLoginInfo lastLoginInfo) { - return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); + } + + @Override + public LockedTenant with(Instant tenantRolesLastMaintained) { + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } } @@ -134,8 +143,8 @@ public abstract class LockedTenant { private Cloud(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<SimplePrincipal> creator, BiMap<PublicKey, SimplePrincipal> developerKeys, TenantInfo info, - List<TenantSecretStore> tenantSecretStores, ArchiveAccess archiveAccess, Optional<Instant> invalidateUserSessionsBefore) { - super(name, createdAt, lastLoginInfo); + List<TenantSecretStore> tenantSecretStores, ArchiveAccess archiveAccess, Optional<Instant> invalidateUserSessionsBefore, Instant tenantRolesLastMaintained) { + super(name, createdAt, lastLoginInfo, tenantRolesLastMaintained); this.developerKeys = ImmutableBiMap.copyOf(developerKeys); this.creator = creator; this.info = info; @@ -145,12 +154,12 @@ public abstract class LockedTenant { } private Cloud(CloudTenant tenant) { - this(tenant.name(), tenant.createdAt(), tenant.lastLoginInfo(), tenant.creator(), tenant.developerKeys(), tenant.info(), tenant.tenantSecretStores(), tenant.archiveAccess(), tenant.invalidateUserSessionsBefore()); + this(tenant.name(), tenant.createdAt(), tenant.lastLoginInfo(), tenant.creator(), tenant.developerKeys(), tenant.info(), tenant.tenantSecretStores(), tenant.archiveAccess(), tenant.invalidateUserSessionsBefore(), tenant.tenantRolesLastMaintained()); } @Override public CloudTenant get() { - return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withDeveloperKey(PublicKey key, Principal principal) { @@ -161,42 +170,47 @@ public abstract class LockedTenant { if (keys.inverse().containsKey(simplePrincipal)) throw new IllegalArgumentException(principal + " is already associated with key " + KeyUtils.toPem(keys.inverse().get(simplePrincipal))); keys.put(key, simplePrincipal); - return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withoutDeveloperKey(PublicKey key) { BiMap<PublicKey, SimplePrincipal> keys = HashBiMap.create(developerKeys); keys.remove(key); - return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withInfo(TenantInfo newInfo) { - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, newInfo, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, newInfo, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } @Override public LockedTenant with(LastLoginInfo lastLoginInfo) { - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withSecretStore(TenantSecretStore tenantSecretStore) { ArrayList<TenantSecretStore> secretStores = new ArrayList<>(tenantSecretStores); secretStores.add(tenantSecretStore); - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withoutSecretStore(TenantSecretStore tenantSecretStore) { ArrayList<TenantSecretStore> secretStores = new ArrayList<>(tenantSecretStores); secretStores.remove(tenantSecretStore); - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, secretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } public Cloud withArchiveAccess(ArchiveAccess archiveAccess) { - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore,tenantRolesLastMaintained); } public Cloud withInvalidateUserSessionsBefore(Instant invalidateUserSessionsBefore) { - return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, Optional.of(invalidateUserSessionsBefore)); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, Optional.of(invalidateUserSessionsBefore), tenantRolesLastMaintained); + } + + @Override + public LockedTenant with(Instant tenantRolesLastMaintained) { + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } } @@ -207,7 +221,7 @@ public abstract class LockedTenant { private final Instant deletedAt; private Deleted(DeletedTenant tenant) { - super(tenant.name(), tenant.createdAt(), tenant.lastLoginInfo()); + super(tenant.name(), tenant.createdAt(), tenant.lastLoginInfo(), Instant.EPOCH); this.deletedAt = tenant.deletedAt(); } @@ -220,6 +234,11 @@ public abstract class LockedTenant { public LockedTenant with(LastLoginInfo lastLoginInfo) { return this; } + + @Override + public LockedTenant with(Instant tenantRolesLastMaintained) { + return this; + } } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java index b6d0155b6ab..d4536da91fe 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java @@ -83,6 +83,7 @@ public class TenantSerializer { private static final String awsArchiveAccessRoleField = "awsArchiveAccessRole"; private static final String gcpArchiveAccessMemberField = "gcpArchiveAccessMember"; private static final String invalidateUserSessionsBeforeField = "invalidateUserSessionsBefore"; + private static final String tenantRolesLastMaintainedField = "tenantRolesLastMaintained"; private static final String awsIdField = "awsId"; private static final String roleField = "role"; @@ -94,6 +95,7 @@ public class TenantSerializer { tenantObject.setString(typeField, valueOf(tenant.type())); tenantObject.setLong(createdAtField, tenant.createdAt().toEpochMilli()); toSlime(tenant.lastLoginInfo(), tenantObject.setObject(lastLoginInfoField)); + tenantObject.setLong(tenantRolesLastMaintainedField, tenant.tenantRolesLastMaintained().toEpochMilli()); switch (tenant.type()) { case athenz: toSlime((AthenzTenant) tenant, tenantObject); break; @@ -178,7 +180,8 @@ public class TenantSerializer { Optional<Contact> contact = contactFrom(tenantObject.field(contactField)); Instant createdAt = SlimeUtils.instant(tenantObject.field(createdAtField)); LastLoginInfo lastLoginInfo = lastLoginInfoFromSlime(tenantObject.field(lastLoginInfoField)); - return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); + Instant tenantRolesLastMaintained = SlimeUtils.instant(tenantObject.field(tenantRolesLastMaintainedField)); + return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo, tenantRolesLastMaintained); } private CloudTenant cloudTenantFrom(Inspector tenantObject) { @@ -191,7 +194,8 @@ public class TenantSerializer { List<TenantSecretStore> tenantSecretStores = secretStoresFromSlime(tenantObject.field(secretStoresField)); ArchiveAccess archiveAccess = archiveAccessFromSlime(tenantObject); Optional<Instant> invalidateUserSessionsBefore = SlimeUtils.optionalInstant(tenantObject.field(invalidateUserSessionsBeforeField)); - return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore); + Instant tenantRolesLastMaintained = SlimeUtils.instant(tenantObject.field(tenantRolesLastMaintainedField)); + return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info, tenantSecretStores, archiveAccess, invalidateUserSessionsBefore, tenantRolesLastMaintained); } private DeletedTenant deletedTenantFrom(Inspector tenantObject) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java index 852d4847b7e..cd1debc71fd 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java @@ -63,7 +63,8 @@ public class NotificationsDbTest { email)))), List.of(), new ArchiveAccess(), - Optional.empty()); + Optional.empty(), + Instant.EPOCH); private static final List<Notification> notifications = List.of( notification(1001, Type.deployment, Level.error, NotificationSource.from(tenant), "tenant msg"), notification(1101, Type.applicationPackage, Level.warning, NotificationSource.from(TenantAndApplicationId.from(tenant.value(), "app1")), "app msg"), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java index ecf42979b40..0c031a13e6f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java @@ -44,7 +44,8 @@ public class NotifierTest { email)))), List.of(), new ArchiveAccess(), - Optional.empty()); + Optional.empty(), + Instant.EPOCH); MockCuratorDb curatorDb = new MockCuratorDb(SystemName.Public); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java index 5144c5cb7b4..8da0d665282 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java @@ -89,7 +89,8 @@ public class TenantSerializerTest { Optional.of(new PropertyId("1")), Optional.of(contact()), Instant.EPOCH, - lastLoginInfo(321L, 654L, 987L)); + lastLoginInfo(321L, 654L, 987L), + Instant.EPOCH); AthenzTenant serialized = (AthenzTenant) serializer.tenantFrom(serializer.toSlime(tenant)); assertEquals(tenant.contact(), serialized.contact()); } @@ -105,7 +106,8 @@ public class TenantSerializerTest { TenantInfo.empty(), List.of(), new ArchiveAccess(), - Optional.empty()); + Optional.empty(), + Instant.EPOCH); CloudTenant serialized = (CloudTenant) serializer.tenantFrom(serializer.toSlime(tenant)); assertEquals(tenant.name(), serialized.name()); assertEquals(tenant.creator(), serialized.creator()); @@ -127,7 +129,8 @@ public class TenantSerializerTest { new TenantSecretStore("ss2", "124", "role2") ), new ArchiveAccess().withAWSRole("arn:aws:iam::123456789012:role/my-role"), - Optional.of(Instant.ofEpochMilli(1234567))); + Optional.of(Instant.ofEpochMilli(1234567)), + Instant.EPOCH); CloudTenant serialized = (CloudTenant) serializer.tenantFrom(serializer.toSlime(tenant)); assertEquals(tenant.info(), serialized.info()); assertEquals(tenant.tenantSecretStores(), serialized.tenantSecretStores()); @@ -177,7 +180,8 @@ public class TenantSerializerTest { TenantInfo.empty(), List.of(), new ArchiveAccess().withAWSRole("arn:aws:iam::123456789012:role/my-role").withGCPMember("user:foo@example.com"), - Optional.empty()); + Optional.empty(), + Instant.EPOCH); CloudTenant serialized = (CloudTenant) serializer.tenantFrom(serializer.toSlime(tenant)); assertEquals(serialized.archiveAccess().awsRole().get(), "arn:aws:iam::123456789012:role/my-role"); assertEquals(serialized.archiveAccess().gcpMember().get(), "user:foo@example.com"); @@ -246,6 +250,19 @@ public class TenantSerializerTest { assertEquals(tenant.deletedAt(), serialized.deletedAt()); } + @Test + void tenant_with_roles_maintained() { + AthenzTenant tenant = new AthenzTenant(TenantName.from("athenz-tenant"), + new AthenzDomain("domain1"), + new Property("property1"), + Optional.of(new PropertyId("1")), + Optional.of(contact()), + Instant.EPOCH, + lastLoginInfo(321L, 654L, 987L), + Instant.ofEpochMilli(1_000_000)); + assertEquals(tenant, serializer.tenantFrom(serializer.toSlime(tenant))); + } + private static Contact contact() { return new Contact( URI.create("http://contact1.test"), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index f1381ead221..d40485ff5c0 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -1287,7 +1287,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // Create legacy tenant name containing underscores tester.controller().curator().writeTenant(new AthenzTenant(TenantName.from("my_tenant"), ATHENZ_TENANT_DOMAIN, - new Property("property1"), Optional.empty(), Optional.empty(), Instant.EPOCH, LastLoginInfo.EMPTY)); + new Property("property1"), Optional.empty(), Optional.empty(), Instant.EPOCH, LastLoginInfo.EMPTY, Instant.EPOCH)); // POST (add) a Athenz tenant with dashes duplicates existing one with underscores tester.assertResponse(request("/application/v4/tenant/my-tenant", POST) diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java index fcbecfa2e68..410bb801e85 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java @@ -78,7 +78,8 @@ public class SignatureFilterTest { TenantInfo.empty(), List.of(), new ArchiveAccess(), - Optional.empty())); + Optional.empty(), + Instant.EPOCH)); tester.curator().writeApplication(new Application(appId, tester.clock().instant())); } @@ -125,7 +126,8 @@ public class SignatureFilterTest { TenantInfo.empty(), List.of(), new ArchiveAccess(), - Optional.empty())); + Optional.empty(), + Instant.EPOCH)); verifySecurityContext(requestOf(signer.signed(request.copy(), Method.POST, () -> new ByteArrayInputStream(hiBytes)), hiBytes), new SecurityContext(new SimplePrincipal("user"), Set.of(Role.reader(id.tenant()), |