Skip to content

Commit

Permalink
adding support for cert expiry time (AthenZ#1455)
Browse files Browse the repository at this point in the history
Signed-off-by: jothi avanachandu <[email protected]>

Co-authored-by: jothi avanachandu <[email protected]>
  • Loading branch information
jothi-prasad and jothi avanachandu authored Apr 25, 2021
1 parent cb26d3d commit 50deea1
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 47 deletions.
11 changes: 11 additions & 0 deletions core/zts/src/main/java/com/yahoo/athenz/zts/Workload.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class Workload {
public String hostname;
public String provider;
public Timestamp updateTime;
public Timestamp certExpiryTime;

public Workload setDomainName(String domainName) {
this.domainName = domainName;
Expand Down Expand Up @@ -69,6 +70,13 @@ public Workload setUpdateTime(Timestamp updateTime) {
public Timestamp getUpdateTime() {
return updateTime;
}
public Workload setCertExpiryTime(Timestamp certExpiryTime) {
this.certExpiryTime = certExpiryTime;
return this;
}
public Timestamp getCertExpiryTime() {
return certExpiryTime;
}

@Override
public boolean equals(Object another) {
Expand Down Expand Up @@ -98,6 +106,9 @@ public boolean equals(Object another) {
if (updateTime == null ? a.updateTime != null : !updateTime.equals(a.updateTime)) {
return false;
}
if (certExpiryTime == null ? a.certExpiryTime != null : !certExpiryTime.equals(a.certExpiryTime)) {
return false;
}
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion core/zts/src/main/java/com/yahoo/athenz/zts/ZTSSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@ private static Schema build() {
.arrayField("ipAddresses", "String", false, "list of IP addresses associated with the workload, optional for getWorkloadsByIP API call")
.field("hostname", "String", false, "hostname associated with the workload")
.field("provider", "String", false, "infrastructure provider e.g. k8s, AWS, Azure, openstack etc.")
.field("updateTime", "Timestamp", false, "most recent update timestamp in the backend");
.field("updateTime", "Timestamp", false, "most recent update timestamp in the backend")
.field("certExpiryTime", "Timestamp", false, "certificate expiry time (ex: getNotAfter)");

sb.structType("Workloads")
.arrayField("workloadList", "Workload", false, "list of workloads");
Expand Down
1 change: 1 addition & 0 deletions core/zts/src/main/rdl/Workload.tdl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Workload Struct {
String hostname; //hostname associated with the workload
String provider; // infrastructure provider e.g. k8s, AWS, Azure, openstack etc.
Timestamp updateTime; // most recent update timestamp in the backend
Timestamp certExpiryTime; // certificate expiry time (ex: getNotAfter)
}

type Workloads Struct {
Expand Down
11 changes: 9 additions & 2 deletions core/zts/src/test/java/com/yahoo/athenz/zts/WorkloadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void testWorkloadFields() {
Workload wl1 = new Workload();
List<String> ipAddresses = Collections.singletonList("10.20.30.40");
wl1.setDomainName("athenz").setServiceName("api").setIpAddresses(ipAddresses).setProvider("kubernetes").setUuid("1234-rsaq-422dcz")
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1");
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1").setCertExpiryTime(Timestamp.fromMillis(123456789123L));

assertNotNull(wl1);
assertEquals(wl1.getDomainName(), "athenz");
Expand All @@ -40,11 +40,12 @@ public void testWorkloadFields() {
assertEquals(wl1.getUuid(), "1234-rsaq-422dcz");
assertEquals(wl1.getUpdateTime(), Timestamp.fromMillis(123456789123L));
assertEquals(wl1.getHostname(), "testhost-1");
assertEquals(wl1.getCertExpiryTime(), Timestamp.fromMillis(123456789123L));
assertEquals(wl1, wl1);

Workload wl2 = new Workload();
wl2.setDomainName("athenz").setServiceName("api").setIpAddresses(ipAddresses).setProvider("kubernetes").setUuid("1234-rsaq-422dcz")
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1");
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1").setCertExpiryTime(Timestamp.fromMillis(123456789123L));

assertEquals(wl1, wl2);

Expand Down Expand Up @@ -88,6 +89,12 @@ public void testWorkloadFields() {
assertNotEquals(wl1, wl2);

wl2.setHostname("testhost-1");
wl2.setCertExpiryTime(Timestamp.fromMillis(123456789000L));
assertNotEquals(wl1, wl2);
wl2.setCertExpiryTime(null);
assertNotEquals(wl1, wl2);

wl2.setCertExpiryTime(Timestamp.fromMillis(123456789123L));
assertEquals(wl1, wl2);

assertNotEquals(wl1, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void testWorkloadsFields() {
Workload wl1 = new Workload();
List<String> ipAddresses = Collections.singletonList("10.20.30.40");
wl1.setDomainName("athenz").setServiceName("api").setIpAddresses(ipAddresses).setProvider("kubernetes").setUuid("1234-rsaq-422dcz")
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1");
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1").setCertExpiryTime(Timestamp.fromMillis(123456789123L));

List<Workload> workloadList1 = Collections.singletonList(wl1);

Expand All @@ -43,7 +43,7 @@ public void testWorkloadsFields() {
Workloads workloads2 = new Workloads();
Workload wl2 = new Workload();
wl2.setDomainName("athenz").setServiceName("api").setIpAddresses(ipAddresses).setProvider("kubernetes").setUuid("1234-rsaq-422dcz")
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1");
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1").setCertExpiryTime(Timestamp.fromMillis(123456789123L));

List<Workload> workloadList2 = Collections.singletonList(wl2);
workloads2.setWorkloadList(workloadList2);
Expand All @@ -58,7 +58,7 @@ public void testWorkloadsFields() {

Workload wl3 = new Workload();
wl3.setDomainName("athenz").setServiceName("api").setIpAddresses(ipAddresses).setProvider("openstack").setUuid("1234-acbf")
.setUpdateTime(Timestamp.fromMillis(123456789123L));
.setUpdateTime(Timestamp.fromMillis(123456789123L)).setHostname("testhost-1").setCertExpiryTime(Timestamp.fromMillis(123456789123L));

List<Workload> workloadList3 = Collections.singletonList(wl3);
workloads2.setWorkloadList(workloadList3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ public class WorkloadRecord {
private Date updateTime;
private String hostname;

public Date getCertExpiryTime() {
return certExpiryTime;
}

public void setCertExpiryTime(Date certExpiryTime) {
this.certExpiryTime = certExpiryTime;
}

private Date certExpiryTime;
public String getHostname() {
return hostname;
}
Expand Down Expand Up @@ -91,6 +100,7 @@ public String toString() {
", creationTime=" + creationTime +
", updateTime=" + updateTime +
", hostname='" + hostname + '\'' +
", certExpiryTime=" + certExpiryTime +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,19 @@ public void testWorkloadRecord() {
wr.setIp("10.0.0.1");
wr.setProvider("aws");
wr.setInstanceId("afve-24dq2d");
wr.setHostname("test-host1");
Date date = new Date();
wr.setCreationTime(date);
wr.setUpdateTime(date);
wr.setCertExpiryTime(date);

assertEquals(wr.getService(), "athenz.api");
assertEquals(wr.getIp(), "10.0.0.1");
assertEquals(wr.getProvider(), "aws");
assertEquals(wr.getInstanceId(), "afve-24dq2d");
assertEquals(wr.getHostname(), "test-host1");
assertEquals(wr.getCreationTime(), date);
assertEquals(wr.getUpdateTime(), date);
assertEquals(wr.getCertExpiryTime(), date);
}
}
4 changes: 3 additions & 1 deletion servers/zts/schema/updates/update-20210420.sql
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
ALTER TABLE `zts_store`.`workloads` ADD COLUMN `hostname` VARCHAR(256) NOT NULL;
ALTER TABLE `zts_store`.`workloads`
ADD COLUMN `hostname` VARCHAR(256) NOT NULL DEFAULT 'NA',
ADD COLUMN `certExpiryTime` DATETIME(3) NOT NULL DEFAULT '1970-01-01 00:00:00.000';
3 changes: 2 additions & 1 deletion servers/zts/schema/zts_server.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ CREATE TABLE IF NOT EXISTS `zts_store`.`workloads` (
`service` VARCHAR(384) NOT NULL,
`ip` VARCHAR(64) NOT NULL,
`instanceId` VARCHAR(256) NOT NULL,
`hostname` VARCHAR(256) NOT NULL,
`hostname` VARCHAR(256) NOT NULL DEFAULT 'NA',
`creationTime` DATETIME(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
`updateTime` DATETIME(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
`certExpiryTime` DATETIME(3) NOT NULL DEFAULT '1970-01-01 00:00:00.000',
PRIMARY KEY (`instanceId`, `ip`, `service`),
INDEX `idx_service` (`service` ASC),
INDEX `idx_ip` (`ip` ASC))
Expand Down
17 changes: 13 additions & 4 deletions servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2906,7 +2906,7 @@ public Response postInstanceRegisterInformation(ResourceContext ctx, InstanceReg

if (enableWorkloadStore && !athenzSysDomainCache.isWorkloadStoreExcludedProvider(provider)) {
// insert into workloads store is on best-effort basis. No errors are thrown if the op is not successful.
insertWorkloadRecord(cn, provider, certReqInstanceId, sanIpStrForWorkloadStore, info.getHostname());
insertWorkloadRecord(cn, provider, certReqInstanceId, sanIpStrForWorkloadStore, info.getHostname(), newCert.getNotAfter());
}

// if we're asked to return an NToken in addition to ZTS Certificate
Expand All @@ -2930,7 +2930,7 @@ public Response postInstanceRegisterInformation(ResourceContext ctx, InstanceReg
.header("Location", location).build();
}

void insertWorkloadRecord(String cn, String provider, String certReqInstanceId, String sanIpStr, String hostName) {
void insertWorkloadRecord(String cn, String provider, String certReqInstanceId, String sanIpStr, String hostName, Date certExpiryTime) {
if (StringUtil.isEmpty(sanIpStr)) {
return;
}
Expand All @@ -2951,16 +2951,23 @@ void insertWorkloadRecord(String cn, String provider, String certReqInstanceId,
workloadRecord.setHostname(hostName);
workloadRecord.setCreationTime(new Date());
workloadRecord.setUpdateTime(new Date());
workloadRecord.setCertExpiryTime(certExpiryTime);
if (!instanceCertManager.insertWorkloadRecord(workloadRecord)) {
LOGGER.error("unable to insert workload record={}", workloadRecord);
}
}
}

void updateWorkloadRecord(String cn, String provider, String certReqInstanceId, String sanIpStr) {
void updateWorkloadRecord(String cn, String provider, String certReqInstanceId, String sanIpStr, String hostName, Date certExpiryTime) {
if (StringUtil.isEmpty(sanIpStr)) {
return;
}
if (hostName == null) {
hostName = cn + "." + sanIpStr;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("hostname is not set by agent, hence forming the hostname {} with domain.service {} and sanIpStr {} ..", hostName, cn, sanIpStr);
}
}
WorkloadRecord workloadRecord;
String[] sanIps = sanIpStr.split(",");
Date currDate = new Date();
Expand All @@ -2972,6 +2979,8 @@ void updateWorkloadRecord(String cn, String provider, String certReqInstanceId,
workloadRecord.setService(cn);
workloadRecord.setCreationTime(currDate);
workloadRecord.setUpdateTime(currDate);
workloadRecord.setCertExpiryTime(certExpiryTime);
workloadRecord.setHostname(hostName);
if (!instanceCertManager.updateWorkloadRecord(workloadRecord)) {
LOGGER.error("unable to update workload record={}", workloadRecord);
}
Expand Down Expand Up @@ -3376,7 +3385,7 @@ InstanceIdentity processProviderX509RefreshRequest(ResourceContext ctx, DomainDa

if (enableWorkloadStore && !athenzSysDomainCache.isWorkloadStoreExcludedProvider(provider)) {
// workloads store update is on best-effort basis. No errors are thrown if the op is not successful.
updateWorkloadRecord(AthenzUtils.getPrincipalName(domain, service), provider, instanceId, sanIpStrForWorkloadStore);
updateWorkloadRecord(AthenzUtils.getPrincipalName(domain, service), provider, instanceId, sanIpStrForWorkloadStore, info.getHostname(), newCert.getNotAfter());
}

// log our certificate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,8 @@ public List<Workload> getWorkloadsByService(String domain, String service) {
Map<String, List<String>> flattenedIpAddresses = new HashMap<>();
String mapKey;
for (WorkloadRecord workloadRecord : workloadRecords) {
mapKey = workloadRecord.getInstanceId() + ":" + workloadRecord.getProvider() + ":" + workloadRecord.getUpdateTime().getTime() + ":" + workloadRecord.getHostname();
mapKey = workloadRecord.getInstanceId() + ":" + workloadRecord.getProvider() + ":" + workloadRecord.getUpdateTime().getTime() +
":" + workloadRecord.getCertExpiryTime().getTime() + ":" + workloadRecord.getHostname();
if (flattenedIpAddresses.containsKey(mapKey)) {
flattenedIpAddresses.get(mapKey).add(workloadRecord.getIp());
} else {
Expand All @@ -1087,7 +1088,8 @@ public List<Workload> getWorkloadsByService(String domain, String service) {
wl.setUuid(tempArr[0])
.setProvider(tempArr[1])
.setUpdateTime(Timestamp.fromMillis(Long.parseLong(tempArr[2])))
.setHostname(tempArr[3])
.setCertExpiryTime(Timestamp.fromMillis(Long.parseLong(tempArr[3])))
.setHostname(tempArr[4])
.setIpAddresses(entry.getValue());
return wl;
}).collect(Collectors.toList());
Expand All @@ -1107,8 +1109,8 @@ public List<Workload> getWorkloadsByIp(String ip) {
if (strArr != null) {
wl.setDomainName(strArr[0]).setServiceName(strArr[1]);
}
wl.setProvider(wr.getProvider()).setUuid(wr.getInstanceId()).setUpdateTime(Timestamp.fromDate(wr.getUpdateTime())).setHostname(wr.getHostname());
return wl;
wl.setProvider(wr.getProvider()).setUuid(wr.getInstanceId()).setUpdateTime(Timestamp.fromDate(wr.getUpdateTime()))
.setHostname(wr.getHostname()).setCertExpiryTime(Timestamp.fromDate(wr.getCertExpiryTime())); return wl;
})
.filter(distinctByKey(w -> w.getUuid() + "#" + AthenzUtils.getPrincipalName(w.getDomainName(), w.getServiceName())))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DynamoDBWorkloadRecordStoreConnection implements WorkloadRecordStoreConnection {
Expand All @@ -47,6 +48,8 @@ public class DynamoDBWorkloadRecordStoreConnection implements WorkloadRecordStor
private static final String KEY_CREATION_TIME = "creationTime";
private static final String KEY_UPDATE_TIME = "updateTime";
private static final String KEY_TTL = "ttl";
private static final String KEY_EXPIRY_TIME = "certExpiryTime";
private static final String DEFAULT_HOSTNAME_IF_NULL = "NA";

// the configuration setting is in hours so we'll automatically
// convert into seconds since that's what dynamoDB needs
Expand Down Expand Up @@ -126,10 +129,20 @@ private WorkloadRecord itemToWorkloadRecord(Item item) {
workloadRecord.setInstanceId(item.getString(KEY_INSTANCE_ID));
workloadRecord.setService(item.getString(KEY_SERVICE));
workloadRecord.setIp(item.getString(KEY_IP));
workloadRecord.setHostname(item.getString(KEY_HOSTNAME));

if (item.hasAttribute(KEY_HOSTNAME)) {
workloadRecord.setHostname(item.getString(KEY_HOSTNAME));
} else {
workloadRecord.setHostname(DEFAULT_HOSTNAME_IF_NULL);
}
workloadRecord.setProvider(item.getString(KEY_PROVIDER));
workloadRecord.setCreationTime(DynamoDBUtils.getDateFromItem(item, KEY_CREATION_TIME));
workloadRecord.setUpdateTime(DynamoDBUtils.getDateFromItem(item, KEY_UPDATE_TIME));
if (item.hasAttribute(KEY_EXPIRY_TIME)) {
workloadRecord.setCertExpiryTime(DynamoDBUtils.getDateFromItem(item, KEY_EXPIRY_TIME));
} else {
workloadRecord.setCertExpiryTime(new Date(0)); //setting default date to 01/01/1970.
}

return workloadRecord;
}
Expand All @@ -148,6 +161,8 @@ public boolean updateWorkloadRecord(WorkloadRecord workloadRecord) {
new AttributeUpdate(KEY_INSTANCE_ID).put(workloadRecord.getInstanceId()),
new AttributeUpdate(KEY_CREATION_TIME).put(DynamoDBUtils.getLongFromDate(workloadRecord.getCreationTime())),
new AttributeUpdate(KEY_UPDATE_TIME).put(DynamoDBUtils.getLongFromDate(workloadRecord.getUpdateTime())),
new AttributeUpdate(KEY_EXPIRY_TIME).put(DynamoDBUtils.getLongFromDate(workloadRecord.getCertExpiryTime())),
new AttributeUpdate(KEY_HOSTNAME).put(workloadRecord.getHostname()),
new AttributeUpdate(KEY_TTL).put(workloadRecord.getUpdateTime().getTime() / 1000L + expiryTime)
);
updateItemRetryDynamoDBCommand.run(() -> table.updateItem(updateItemSpec));
Expand All @@ -170,6 +185,7 @@ public boolean insertWorkloadRecord(WorkloadRecord workloadRecord) {
.withString(KEY_HOSTNAME, workloadRecord.getHostname())
.with(KEY_CREATION_TIME, DynamoDBUtils.getLongFromDate(workloadRecord.getCreationTime()))
.with(KEY_UPDATE_TIME, DynamoDBUtils.getLongFromDate(workloadRecord.getUpdateTime()))
.with(KEY_EXPIRY_TIME, DynamoDBUtils.getLongFromDate(workloadRecord.getCertExpiryTime()))
.withLong(KEY_TTL, workloadRecord.getUpdateTime().getTime() / 1000L + expiryTime);
putItemRetryDynamoDBCommand.run(() -> table.putItem(item));
return true;
Expand Down
Loading

0 comments on commit 50deea1

Please sign in to comment.