Skip to content

feat(lib): add fallback to namespace kas #166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
edc3ba6
Update pom.xml
mkleene Jul 16, 2024
2cda7db
fix: add logging to cmdline
mkleene Jul 23, 2024
69c7f83
configure
mkleene Jul 23, 2024
d99822e
Merge remote-tracking branch 'origin/mkleene-patch-3' into mkleene-pa…
mkleene Jul 23, 2024
ec5b752
make this work
mkleene Jul 23, 2024
84d9b26
Update log4j2.xml
mkleene Jul 23, 2024
f542ccc
Update log4j2.xml
mkleene Jul 23, 2024
17ee417
fix config
mkleene Jul 23, 2024
349474e
Merge remote-tracking branch 'origin/mkleene-patch-3' into mkleene-pa…
mkleene Jul 23, 2024
e9eddff
Merge branch 'main' into mkleene-patch-3
mkleene Aug 13, 2024
222f1de
Merge branch 'main' into mkleene-patch-3
mkleene Aug 29, 2024
eadda38
add a grant on the namespace
mkleene Sep 19, 2024
4ce00a7
Merge remote-tracking branch 'origin/main' into feature/add-namespace…
mkleene Sep 19, 2024
2408297
refactor
mkleene Sep 19, 2024
c089b6b
debug
mkleene Sep 19, 2024
59a286c
add an empty grant
mkleene Sep 19, 2024
391bd22
do not need this
mkleene Sep 19, 2024
0641c4a
Merge remote-tracking branch 'origin/mkleene-patch-3' into feature/ad…
mkleene Sep 19, 2024
321d743
add a log message
mkleene Sep 19, 2024
e59e2d5
re-enable tests
mkleene Sep 20, 2024
4fcc939
rename
mkleene Sep 20, 2024
a1d3805
add logging
mkleene Sep 20, 2024
c5a37fc
account for the fact that this may not come back from the service
mkleene Sep 20, 2024
2cfaf65
whitespace noise
mkleene Sep 20, 2024
490b787
Update AutoconfigureTest.java
mkleene Sep 20, 2024
02759a0
Update sdk/src/test/java/io/opentdf/platform/sdk/AutoconfigureTest.java
mkleene Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion cmdline/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,22 @@
<artifactId>picocli</artifactId>
<version>4.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentdf.platform</groupId>
<artifactId>sdk</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
</project>
16 changes: 16 additions & 0 deletions cmdline/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
<appenders>
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</appenders>
<loggers>
<root level="trace">
<appender-ref ref="Console"/>
</root>
<Logger name="io.grpc.netty" level="error" additivity="false">
<AppenderRef ref="Console" />
</Logger>
</loggers>
</configuration>
150 changes: 75 additions & 75 deletions sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
package io.opentdf.platform.sdk;

import com.google.common.base.Supplier;
import io.opentdf.platform.policy.Attribute;
import io.opentdf.platform.policy.AttributeRuleTypeEnum;
import io.opentdf.platform.policy.AttributeValueSelector;
import io.opentdf.platform.policy.KasPublicKey;
import io.opentdf.platform.policy.KasPublicKeyAlgEnum;
import io.opentdf.platform.policy.KeyAccessServer;
import io.opentdf.platform.policy.Value;
import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsRequest;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse.AttributeAndValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
Expand All @@ -19,23 +35,6 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Supplier;

import io.opentdf.platform.policy.KeyAccessServer;
import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsRequest;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse.AttributeAndValue;
import io.opentdf.platform.policy.Attribute;
import io.opentdf.platform.policy.Value;
import io.opentdf.platform.policy.KasPublicKey;
import io.opentdf.platform.policy.AttributeValueSelector;
import io.opentdf.platform.policy.AttributeRuleTypeEnum;
import io.opentdf.platform.policy.KasPublicKeyAlgEnum;

// Attribute rule types: operators!
class RuleType {
public static final String HIERARCHY = "hierarchy";
Expand Down Expand Up @@ -349,7 +348,7 @@ BooleanKeyExpression insertKeysForAttribute(AttributeBooleanExpression e) throws
}

String op = ruleToOperator(clause.def.getRule());
if (op == RuleType.UNSPECIFIED) {
if (op.equals(RuleType.UNSPECIFIED)) {
logger.warn("Unknown attribute rule type: " + clause);
}

Expand Down Expand Up @@ -672,80 +671,81 @@ public static String ruleToOperator(AttributeRuleTypeEnum e) {

}

// Given a policy (list of data attributes or tags),
// get a set of grants from attribute values to KASes.
// Unlike `NewGranterFromService`, this works offline.
public static Granter newGranterFromAttributes(Value... attrValues) throws AutoConfigureException {
var attrsAndValues = Arrays.stream(attrValues).map(v -> {
if (!v.hasAttribute()) {
throw new AutoConfigureException("tried to use an attribute that is not initialized");
}
return AttributeAndValue.newBuilder()
.setValue(v)
.setAttribute(v.getAttribute())
.build();
}).collect(Collectors.toList());

return getGranter(null, attrsAndValues);
}

// Gets a list of directory of KAS grants for a list of attribute FQNs
public static Granter newGranterFromService(AttributesServiceFutureStub as, KASKeyCache keyCache,
AttributeValueFQN... fqns) throws AutoConfigureException, InterruptedException, ExecutionException {
String[] fqnsStr = new String[fqns.length];
for (int i = 0; i < fqns.length; i++) {
fqnsStr[i] = fqns[i].toString();
}
public static Granter newGranterFromService(AttributesServiceFutureStub as, KASKeyCache keyCache, AttributeValueFQN... fqns) throws AutoConfigureException, ExecutionException, InterruptedException {

GetAttributeValuesByFqnsRequest request = GetAttributeValuesByFqnsRequest.newBuilder()
.addAllFqns(Arrays.asList(fqnsStr))
.addAllFqns(Arrays.stream(fqns).map(AttributeValueFQN::toString).collect(Collectors.toList()))
.setWithValue(AttributeValueSelector.newBuilder().setWithKeyAccessGrants(true).build())
.build();

GetAttributeValuesByFqnsResponse av;
av = as.getAttributeValuesByFqns(request).get();
GetAttributeValuesByFqnsResponse av = as.getAttributeValuesByFqns(request).get();

Granter grants = new Granter(Arrays.asList(fqns));
return getGranter(keyCache, new ArrayList<>(av.getFqnAttributeValuesMap().values()));
}

for (Map.Entry<String, GetAttributeValuesByFqnsResponse.AttributeAndValue> entry : av.getFqnAttributeValuesMap()
.entrySet()) {
String fqnstr = entry.getKey();
AttributeAndValue pair = entry.getValue();
private static Granter getGranter(@Nullable KASKeyCache keyCache, List<AttributeAndValue> values) {
Granter grants = new Granter(values.stream().map(AttributeAndValue::getValue).map(Value::getFqn).map(AttributeValueFQN::new).collect(Collectors.toList()));

AttributeValueFQN fqn;
try {
fqn = new AttributeValueFQN(fqnstr);
} catch (Exception e) {
return grants;
}
for (var attributeAndValue: values) {
var val = attributeAndValue.getValue();
var attribute = attributeAndValue.getAttribute();
String fqnstr = val.getFqn();
AttributeValueFQN fqn = new AttributeValueFQN(fqnstr);

Attribute def = pair.getAttribute();
Value v = pair.getValue();
if (v != null && !v.getGrantsList().isEmpty()) {
grants.addAllGrants(fqn, v.getGrantsList(), def);
storeKeysToCache(v.getGrantsList(), keyCache);
} else {
if (def != null) {
grants.addAllGrants(fqn, def.getGrantsList(), def);
storeKeysToCache(def.getGrantsList(), keyCache);
if (!val.getGrantsList().isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("adding grants from attribute value [{}]: {}", val.getFqn(), val.getGrantsList().stream().map(KeyAccessServer::getUri).collect(Collectors.toList()));
}
grants.addAllGrants(fqn, val.getGrantsList(), attribute);
if (keyCache != null) {
storeKeysToCache(val.getGrantsList(), keyCache);
}
} else if (!attribute.getGrantsList().isEmpty()) {
var attributeGrants = attribute.getGrantsList();
if (logger.isDebugEnabled()) {
logger.debug("adding grants from attribute [{}]: {}", attribute.getFqn(), attributeGrants.stream().map(KeyAccessServer::getId).collect(Collectors.toList()));
}
grants.addAllGrants(fqn, attributeGrants, attribute);
if (keyCache != null) {
storeKeysToCache(attributeGrants, keyCache);
}
} else if (!attribute.getNamespace().getGrantsList().isEmpty()) {
var nsGrants = attribute.getNamespace().getGrantsList();
if (logger.isDebugEnabled()) {
logger.debug("adding grants from namespace [{}]: [{}]", attribute.getNamespace().getName(), nsGrants.stream().map(KeyAccessServer::getId).collect(Collectors.toList()));
}
grants.addAllGrants(fqn, nsGrants, attribute);
if (keyCache != null) {
storeKeysToCache(nsGrants, keyCache);
}
} else {
// this is needed to mark the fact that we have an empty
grants.addAllGrants(fqn, List.of(), attribute);
logger.debug("didn't find any grants on value, attribute, or namespace for attribute value [{}]", fqnstr);
}
}

return grants;
}

// Given a policy (list of data attributes or tags),
// get a set of grants from attribute values to KASes.
// Unlike `NewGranterFromService`, this works offline.
public static Granter newGranterFromAttributes(Value... attrs) throws AutoConfigureException {
List<AttributeValueFQN> policyList = new ArrayList<>(attrs.length);

Granter grants = new Granter(policyList);

for (Value v : attrs) {
AttributeValueFQN fqn;
try {
fqn = new AttributeValueFQN(v.getFqn());
} catch (Exception e) {
return grants;
}

grants.policy.add(fqn);
Attribute def = v.getAttribute();
if (def == null) {
throw new AutoConfigureException("No associated definition with value [" + fqn.toString() + "]");
}

grants.addAllGrants(fqn, def.getGrantsList(), def);
grants.addAllGrants(fqn, v.getGrantsList(), def);
}

return grants;
}

static void storeKeysToCache(List<KeyAccessServer> kases, KASKeyCache keyCache) {
for (KeyAccessServer kas : kases) {
Expand Down
Loading
Loading