Skip to content

Commit f884816

Browse files
authored
Enable identity logging on create/update paths (unitycatalog#483)
**PR Checklist** - [x] A description of the changes is added to the description of this PR. - [ ] If there is a related issue, make sure it is linked to this PR. - [ ] If you've fixed a bug or added code that should be tested, add tests! - [ ] If you've added or modified a feature, documentation in `docs` is updated **Description of changes** Enable identity tracking for all create and update paths for securables in UC OSS
1 parent 41f5e11 commit f884816

10 files changed

+88
-12
lines changed

server/src/main/java/io/unitycatalog/server/persist/CatalogRepository.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.unitycatalog.server.persist.utils.PagedListingHelper;
1010
import io.unitycatalog.server.persist.utils.RepositoryUtils;
1111
import io.unitycatalog.server.utils.Constants;
12+
import io.unitycatalog.server.utils.IdentityUtils;
1213
import io.unitycatalog.server.utils.ValidationUtils;
1314
import java.util.ArrayList;
1415
import java.util.Date;
@@ -37,12 +38,18 @@ public static CatalogRepository getInstance() {
3738

3839
public CatalogInfo addCatalog(CreateCatalog createCatalog) {
3940
ValidationUtils.validateSqlObjectName(createCatalog.getName());
41+
String callerId = IdentityUtils.findPrincipalEmailAddress();
42+
Long createTime = System.currentTimeMillis();
4043
CatalogInfo catalogInfo =
4144
new CatalogInfo()
4245
.id(java.util.UUID.randomUUID().toString())
4346
.comment(createCatalog.getComment())
4447
.name(createCatalog.getName())
45-
.createdAt(System.currentTimeMillis())
48+
.owner(callerId)
49+
.createdAt(createTime)
50+
.createdBy(callerId)
51+
.updatedAt(createTime)
52+
.updatedBy(callerId)
4653
.properties(createCatalog.getProperties());
4754

4855
try (Session session = SESSION_FACTORY.openSession()) {
@@ -136,6 +143,7 @@ public CatalogInfo updateCatalog(String name, UpdateCatalog updateCatalog) {
136143
if (updateCatalog.getNewName() != null) {
137144
ValidationUtils.validateSqlObjectName(updateCatalog.getNewName());
138145
}
146+
String callerId = IdentityUtils.findPrincipalEmailAddress();
139147
// can make this just update once we have an identifier that is not the name
140148
try (Session session = SESSION_FACTORY.openSession()) {
141149
Transaction tx = session.beginTransaction();
@@ -171,6 +179,7 @@ && getCatalogDAO(session, updateCatalog.getNewName()) != null) {
171179
.forEach(session::persist);
172180
}
173181
catalogInfoDAO.setUpdatedAt(new Date());
182+
catalogInfoDAO.setUpdatedBy(callerId);
174183
session.merge(catalogInfoDAO);
175184
tx.commit();
176185
CatalogInfo catalogInfo = catalogInfoDAO.toCatalogInfo();

server/src/main/java/io/unitycatalog/server/persist/FunctionRepository.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.unitycatalog.server.persist.utils.PagedListingHelper;
1010
import io.unitycatalog.server.persist.utils.RepositoryUtils;
1111
import io.unitycatalog.server.utils.Constants;
12+
import io.unitycatalog.server.utils.IdentityUtils;
1213
import io.unitycatalog.server.utils.ValidationUtils;
1314
import java.util.ArrayList;
1415
import java.util.List;
@@ -38,6 +39,8 @@ public static FunctionRepository getInstance() {
3839
public FunctionInfo createFunction(CreateFunctionRequest createFunctionRequest) {
3940
ValidationUtils.validateSqlObjectName(createFunctionRequest.getFunctionInfo().getName());
4041
CreateFunction createFunction = createFunctionRequest.getFunctionInfo();
42+
String callerId = IdentityUtils.findPrincipalEmailAddress();
43+
Long createTime = System.currentTimeMillis();
4144
FunctionInfo functionInfo =
4245
new FunctionInfo()
4346
.functionId(UUID.randomUUID().toString())
@@ -46,7 +49,11 @@ public FunctionInfo createFunction(CreateFunctionRequest createFunctionRequest)
4649
.schemaName(createFunction.getSchemaName())
4750
.comment(createFunction.getComment())
4851
.properties(createFunction.getProperties())
49-
.createdAt(System.currentTimeMillis())
52+
.owner(callerId)
53+
.createdAt(createTime)
54+
.createdBy(callerId)
55+
.updatedAt(createTime)
56+
.updatedBy(callerId)
5057
.dataType(createFunction.getDataType())
5158
.fullDataType(createFunction.getFullDataType())
5259
.inputParams(createFunction.getInputParams())

server/src/main/java/io/unitycatalog/server/persist/ModelRepository.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.unitycatalog.server.persist.utils.PagedListingHelper;
1212
import io.unitycatalog.server.persist.utils.RepositoryUtils;
1313
import io.unitycatalog.server.persist.utils.UriUtils;
14+
import io.unitycatalog.server.utils.IdentityUtils;
1415
import io.unitycatalog.server.utils.ValidationUtils;
1516
import java.util.*;
1617
import org.hibernate.Session;
@@ -208,15 +209,19 @@ public RegisteredModelInfo createRegisteredModel(CreateRegisteredModel createReg
208209
ValidationUtils.validateSqlObjectName(createRegisteredModel.getName());
209210
long createTime = System.currentTimeMillis();
210211
String modelId = UUID.randomUUID().toString();
212+
String callerId = IdentityUtils.findPrincipalEmailAddress();
211213
RegisteredModelInfo registeredModelInfo =
212214
new RegisteredModelInfo()
213215
.id(modelId)
214216
.name(createRegisteredModel.getName())
215217
.catalogName(createRegisteredModel.getCatalogName())
216218
.schemaName(createRegisteredModel.getSchemaName())
217219
.comment(createRegisteredModel.getComment())
220+
.owner(callerId)
218221
.createdAt(createTime)
219-
.updatedAt(createTime);
222+
.createdBy(callerId)
223+
.updatedAt(createTime)
224+
.updatedBy(callerId);
220225
String fullName = getRegisteredModelFullName(registeredModelInfo);
221226
registeredModelInfo.setFullName(fullName);
222227
LOGGER.info("Creating Registered Model: " + fullName);
@@ -373,6 +378,7 @@ public RegisteredModelInfo updateRegisteredModel(UpdateRegisteredModel updateReg
373378
String fullName = updateRegisteredModel.getFullName();
374379
LOGGER.info("Updating Registered Model: " + fullName);
375380
RegisteredModelInfo registeredModelInfo;
381+
String callerId = IdentityUtils.findPrincipalEmailAddress();
376382

377383
Transaction tx;
378384
try (Session session = SESSION_FACTORY.openSession()) {
@@ -409,6 +415,7 @@ public RegisteredModelInfo updateRegisteredModel(UpdateRegisteredModel updateReg
409415
}
410416
long updatedTime = System.currentTimeMillis();
411417
origRegisteredModelInfoDAO.setUpdatedAt(new Date(updatedTime));
418+
origRegisteredModelInfoDAO.setUpdatedBy(callerId);
412419
session.persist(origRegisteredModelInfoDAO);
413420
registeredModelInfo = origRegisteredModelInfoDAO.toRegisteredModelInfo();
414421
registeredModelInfo.setCatalogName(catalogName);
@@ -524,6 +531,7 @@ public ModelVersionInfo getModelVersion(String fullName, long version) {
524531

525532
public ModelVersionInfo createModelVersion(CreateModelVersion createModelVersion) {
526533
long createTime = System.currentTimeMillis();
534+
String callerId = IdentityUtils.findPrincipalEmailAddress();
527535
String modelVersionId = UUID.randomUUID().toString();
528536
String catalogName = createModelVersion.getCatalogName();
529537
String schemaName = createModelVersion.getSchemaName();
@@ -539,7 +547,9 @@ public ModelVersionInfo createModelVersion(CreateModelVersion createModelVersion
539547
.status(ModelVersionStatus.PENDING_REGISTRATION)
540548
.comment(createModelVersion.getComment())
541549
.createdAt(createTime)
542-
.updatedAt(createTime);
550+
.createdBy(callerId)
551+
.updatedAt(createTime)
552+
.updatedBy(callerId);
543553
String registeredModelFullName = getRegisteredModelFullName(catalogName, schemaName, modelName);
544554
LOGGER.info("Creating Registered Model: " + registeredModelFullName);
545555

@@ -685,6 +695,7 @@ public ModelVersionInfo updateModelVersion(UpdateModelVersion updateModelVersion
685695
Long version = updateModelVersion.getVersion();
686696
LOGGER.info("Updating Model Version: " + fullName + "/" + version);
687697
ModelVersionInfo modelVersionInfo;
698+
String callerId = IdentityUtils.findPrincipalEmailAddress();
688699

689700
Transaction tx;
690701
try (Session session = SESSION_FACTORY.openSession()) {
@@ -702,6 +713,7 @@ public ModelVersionInfo updateModelVersion(UpdateModelVersion updateModelVersion
702713
origModelVersionInfoDAO.setComment(updateModelVersion.getComment());
703714
long updatedTime = System.currentTimeMillis();
704715
origModelVersionInfoDAO.setUpdatedAt(new Date(updatedTime));
716+
origModelVersionInfoDAO.setUpdatedBy(callerId);
705717
session.persist(origModelVersionInfoDAO);
706718
modelVersionInfo = origModelVersionInfoDAO.toModelVersionInfo();
707719
modelVersionInfo.setCatalogName(catalogName);
@@ -774,6 +786,7 @@ public ModelVersionInfo finalizeModelVersion(FinalizeModelVersion finalizeModelV
774786
Long version = finalizeModelVersion.getVersion();
775787
LOGGER.info("Finalize Model Version: " + fullName + "/" + version);
776788
ModelVersionInfo modelVersionInfo;
789+
String callerId = IdentityUtils.findPrincipalEmailAddress();
777790

778791
Transaction tx;
779792
try (Session session = SESSION_FACTORY.openSession()) {
@@ -797,6 +810,7 @@ public ModelVersionInfo finalizeModelVersion(FinalizeModelVersion finalizeModelV
797810
origModelVersionInfoDAO.setStatus(ModelVersionStatus.READY.toString());
798811
long updatedTime = System.currentTimeMillis();
799812
origModelVersionInfoDAO.setUpdatedAt(new Date(updatedTime));
813+
origModelVersionInfoDAO.setUpdatedBy(callerId);
800814
session.persist(origModelVersionInfoDAO);
801815
modelVersionInfo = origModelVersionInfoDAO.toModelVersionInfo();
802816
modelVersionInfo.setCatalogName(catalogName);

server/src/main/java/io/unitycatalog/server/persist/SchemaRepository.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.unitycatalog.server.persist.utils.PagedListingHelper;
1111
import io.unitycatalog.server.persist.utils.RepositoryUtils;
1212
import io.unitycatalog.server.utils.Constants;
13+
import io.unitycatalog.server.utils.IdentityUtils;
1314
import io.unitycatalog.server.utils.ValidationUtils;
1415
import java.util.*;
1516
import org.hibernate.Session;
@@ -36,6 +37,7 @@ public static SchemaRepository getInstance() {
3637

3738
public SchemaInfo createSchema(CreateSchema createSchema) {
3839
ValidationUtils.validateSqlObjectName(createSchema.getName());
40+
String callerId = IdentityUtils.findPrincipalEmailAddress();
3941
try (Session session = SESSION_FACTORY.openSession()) {
4042
Transaction tx = session.beginTransaction();
4143
try {
@@ -45,13 +47,18 @@ public SchemaInfo createSchema(CreateSchema createSchema) {
4547
}
4648
CatalogInfoDAO catalogDAO =
4749
CATALOG_REPOSITORY.getCatalogDAO(session, createSchema.getCatalogName());
50+
Long createTime = System.currentTimeMillis();
4851
SchemaInfo schemaInfo =
4952
new SchemaInfo()
5053
.schemaId(UUID.randomUUID().toString())
5154
.name(createSchema.getName())
5255
.catalogName(createSchema.getCatalogName())
5356
.comment(createSchema.getComment())
54-
.createdAt(System.currentTimeMillis())
57+
.owner(callerId)
58+
.createdAt(createTime)
59+
.createdBy(callerId)
60+
.updatedAt(createTime)
61+
.updatedBy(callerId)
5562
.properties(createSchema.getProperties());
5663
SchemaInfoDAO schemaInfoDAO = SchemaInfoDAO.from(schemaInfo);
5764
schemaInfoDAO.setCatalogId(catalogDAO.getId());
@@ -186,6 +193,7 @@ public SchemaInfo updateSchema(String fullName, UpdateSchema updateSchema) {
186193
if (updateSchema.getNewName() != null) {
187194
ValidationUtils.validateSqlObjectName(updateSchema.getNewName());
188195
}
196+
String callerId = IdentityUtils.findPrincipalEmailAddress();
189197
try (Session session = SESSION_FACTORY.openSession()) {
190198
Transaction tx = session.beginTransaction();
191199
try {
@@ -220,6 +228,7 @@ public SchemaInfo updateSchema(String fullName, UpdateSchema updateSchema) {
220228
.forEach(session::persist);
221229
}
222230
schemaInfoDAO.setUpdatedAt(new Date());
231+
schemaInfoDAO.setUpdatedBy(callerId);
223232
session.merge(schemaInfoDAO);
224233
tx.commit();
225234
return convertFromDAO(session, schemaInfoDAO, fullName);

server/src/main/java/io/unitycatalog/server/persist/TableRepository.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.unitycatalog.server.persist.utils.PagedListingHelper;
1212
import io.unitycatalog.server.persist.utils.RepositoryUtils;
1313
import io.unitycatalog.server.utils.Constants;
14+
import io.unitycatalog.server.utils.IdentityUtils;
1415
import io.unitycatalog.server.utils.ValidationUtils;
1516
import java.util.*;
1617
import java.util.stream.Collectors;
@@ -105,10 +106,12 @@ private TableInfoDAO findTable(
105106

106107
public TableInfo createTable(CreateTable createTable) {
107108
ValidationUtils.validateSqlObjectName(createTable.getName());
109+
String callerId = IdentityUtils.findPrincipalEmailAddress();
108110
List<ColumnInfo> columnInfos =
109111
createTable.getColumns().stream()
110112
.map(c -> c.typeText(c.getTypeText().toLowerCase(Locale.ROOT)))
111113
.collect(Collectors.toList());
114+
Long createTime = System.currentTimeMillis();
112115
TableInfo tableInfo =
113116
new TableInfo()
114117
.tableId(UUID.randomUUID().toString())
@@ -121,7 +124,11 @@ public TableInfo createTable(CreateTable createTable) {
121124
.storageLocation(FileUtils.convertRelativePathToURI(createTable.getStorageLocation()))
122125
.comment(createTable.getComment())
123126
.properties(createTable.getProperties())
124-
.createdAt(System.currentTimeMillis());
127+
.owner(callerId)
128+
.createdAt(createTime)
129+
.createdBy(callerId)
130+
.updatedAt(createTime)
131+
.updatedBy(callerId);
125132
String fullName = getTableFullName(tableInfo);
126133
LOGGER.debug("Creating table: " + fullName);
127134

server/src/main/java/io/unitycatalog/server/persist/VolumeRepository.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.unitycatalog.server.persist.dao.VolumeInfoDAO;
88
import io.unitycatalog.server.persist.utils.FileUtils;
99
import io.unitycatalog.server.persist.utils.HibernateUtils;
10+
import io.unitycatalog.server.utils.IdentityUtils;
1011
import io.unitycatalog.server.utils.ValidationUtils;
1112
import java.util.Date;
1213
import java.util.Optional;
@@ -40,14 +41,20 @@ public VolumeInfo createVolume(CreateVolumeRequestContent createVolumeRequest) {
4041
+ createVolumeRequest.getSchemaName()
4142
+ "."
4243
+ createVolumeRequest.getName();
44+
String callerId = IdentityUtils.findPrincipalEmailAddress();
45+
Long createTime = System.currentTimeMillis();
4346
VolumeInfo volumeInfo = new VolumeInfo();
4447
volumeInfo.setVolumeId(UUID.randomUUID().toString());
4548
volumeInfo.setCatalogName(createVolumeRequest.getCatalogName());
4649
volumeInfo.setSchemaName(createVolumeRequest.getSchemaName());
4750
volumeInfo.setName(createVolumeRequest.getName());
4851
volumeInfo.setComment(createVolumeRequest.getComment());
4952
volumeInfo.setFullName(volumeFullName);
50-
volumeInfo.setCreatedAt(System.currentTimeMillis());
53+
volumeInfo.setOwner(callerId);
54+
volumeInfo.setCreatedAt(createTime);
55+
volumeInfo.setCreatedBy(callerId);
56+
volumeInfo.setUpdatedAt(createTime);
57+
volumeInfo.setUpdatedBy(callerId);
5158
volumeInfo.setVolumeType(createVolumeRequest.getVolumeType());
5259
if (VolumeType.MANAGED.equals(createVolumeRequest.getVolumeType())) {
5360
throw new BaseException(
@@ -216,6 +223,7 @@ public VolumeInfo updateVolume(String name, UpdateVolumeRequestContent updateVol
216223
if (updateVolumeRequest.getNewName() != null) {
217224
ValidationUtils.validateSqlObjectName(updateVolumeRequest.getNewName());
218225
}
226+
String callerId = IdentityUtils.findPrincipalEmailAddress();
219227
String[] namespace = name.split("\\.");
220228
String catalog = namespace[0], schema = namespace[1], volume = namespace[2];
221229
try (Session session = SESSION_FACTORY.openSession()) {
@@ -245,6 +253,7 @@ public VolumeInfo updateVolume(String name, UpdateVolumeRequestContent updateVol
245253
volumeInfo.setComment(updateVolumeRequest.getComment());
246254
}
247255
volumeInfo.setUpdatedAt(new Date());
256+
volumeInfo.setUpdatedBy(callerId);
248257
session.merge(volumeInfo);
249258
tx.commit();
250259
LOGGER.info("Updated volume: {}", volumeInfo.getName());

server/src/main/java/io/unitycatalog/server/persist/dao/ModelVersionInfoDAO.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public static ModelVersionInfoDAO from(ModelVersionInfo modelVersionInfo) {
7878
.updatedAt(
7979
modelVersionInfo.getUpdatedAt() != null
8080
? new Date(modelVersionInfo.getUpdatedAt())
81-
: new Date())
81+
: null)
8282
.updatedBy(modelVersionInfo.getUpdatedBy())
8383
.url(modelVersionInfo.getStorageLocation())
8484
.build();

server/src/main/java/io/unitycatalog/server/persist/dao/RegisteredModelInfoDAO.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static RegisteredModelInfoDAO from(RegisteredModelInfo registeredModelInf
6363
.updatedAt(
6464
registeredModelInfo.getUpdatedAt() != null
6565
? new Date(registeredModelInfo.getUpdatedAt())
66-
: new Date())
66+
: null)
6767
.updatedBy(registeredModelInfo.getUpdatedBy())
6868
.url(registeredModelInfo.getStorageLocation())
6969
.build();

server/src/main/java/io/unitycatalog/server/persist/dao/VolumeInfoDAO.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public VolumeInfo toVolumeInfo() {
5757
.owner(owner)
5858
.createdAt(createdAt.getTime())
5959
.createdBy(createdBy)
60-
.updatedAt(updatedAt.getTime())
60+
.updatedAt(updatedAt != null ? updatedAt.getTime() : null)
6161
.updatedBy(updatedBy)
6262
.volumeType(VolumeType.valueOf(volumeType));
6363
}
@@ -75,8 +75,7 @@ public static VolumeInfoDAO from(VolumeInfo volumeInfo) {
7575
.createdAt(
7676
volumeInfo.getCreatedAt() != null ? new Date(volumeInfo.getCreatedAt()) : new Date())
7777
.createdBy(volumeInfo.getCreatedBy())
78-
.updatedAt(
79-
volumeInfo.getUpdatedAt() != null ? new Date(volumeInfo.getUpdatedAt()) : new Date())
78+
.updatedAt(volumeInfo.getUpdatedAt() != null ? new Date(volumeInfo.getUpdatedAt()) : null)
8079
.updatedBy(volumeInfo.getUpdatedBy())
8180
.volumeType(volumeInfo.getVolumeType().getValue())
8281
.build();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.unitycatalog.server.utils;
2+
3+
import com.auth0.jwt.interfaces.Claim;
4+
import com.auth0.jwt.interfaces.DecodedJWT;
5+
import com.linecorp.armeria.server.ServiceRequestContext;
6+
import io.unitycatalog.server.security.JwtClaim;
7+
import io.unitycatalog.server.service.AuthDecorator;
8+
9+
public class IdentityUtils {
10+
11+
public static String findPrincipalEmailAddress() {
12+
ServiceRequestContext ctx = ServiceRequestContext.current();
13+
DecodedJWT decodedJWT = ctx.attr(AuthDecorator.DECODED_JWT_ATTR);
14+
// TODO: if/when authorization becomes mandatory, maybe just throw an exception here?
15+
if (decodedJWT != null) {
16+
Claim sub = decodedJWT.getClaim(JwtClaim.SUBJECT.key());
17+
return sub.asString();
18+
} else {
19+
return null;
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)