1414import org .slf4j .Logger ;
1515import org .slf4j .LoggerFactory ;
1616
17+ import javax .annotation .Nonnull ;
1718import javax .annotation .Nullable ;
1819import java .io .UnsupportedEncodingException ;
1920import java .net .URLDecoder ;
@@ -53,11 +54,11 @@ class RuleType {
5354 * This class includes functionality to create granter instances based on
5455 * attributes either from a list of attribute values or from a service.
5556 */
56- public class Autoconfigure {
57+ class Autoconfigure {
5758
58- public static Logger logger = LoggerFactory .getLogger (Autoconfigure .class );
59+ private static Logger logger = LoggerFactory .getLogger (Autoconfigure .class );
5960
60- public static class KeySplitStep {
61+ static class KeySplitStep {
6162 public String kas ;
6263 public String splitID ;
6364
@@ -93,7 +94,7 @@ public int hashCode() {
9394 }
9495
9596 // Utility class for an attribute name FQN.
96- public static class AttributeNameFQN {
97+ static class AttributeNameFQN {
9798 private final String url ;
9899 private final String key ;
99100
@@ -156,7 +157,7 @@ public String name() throws AutoConfigureException {
156157 }
157158
158159 // Utility class for an attribute value FQN.
159- public static class AttributeValueFQN {
160+ static class AttributeValueFQN {
160161 private final String url ;
161162 private final String key ;
162163
@@ -203,11 +204,11 @@ public int hashCode() {
203204 return Objects .hash (key );
204205 }
205206
206- public String getKey () {
207+ String getKey () {
207208 return key ;
208209 }
209210
210- public String authority () {
211+ String authority () {
211212 Pattern pattern = Pattern .compile ("^(https?://[\\ w./-]+)/attr/\\ S*/value/\\ S*$" );
212213 Matcher matcher = pattern .matcher (url );
213214 if (!matcher .find ()) {
@@ -216,7 +217,7 @@ public String authority() {
216217 return matcher .group (1 );
217218 }
218219
219- public AttributeNameFQN prefix () throws AutoConfigureException {
220+ AttributeNameFQN prefix () throws AutoConfigureException {
220221 Pattern pattern = Pattern .compile ("^(https?://[\\ w./-]+/attr/\\ S*)/value/\\ S*$" );
221222 Matcher matcher = pattern .matcher (url );
222223 if (!matcher .find ()) {
@@ -225,7 +226,7 @@ public AttributeNameFQN prefix() throws AutoConfigureException {
225226 return new AttributeNameFQN (matcher .group (1 ));
226227 }
227228
228- public String value () {
229+ String value () {
229230 Pattern pattern = Pattern .compile ("^https?://[\\ w./-]+/attr/\\ S*/value/(\\ S*)$" );
230231 Matcher matcher = pattern .matcher (url );
231232 if (!matcher .find ()) {
@@ -238,21 +239,21 @@ public String value() {
238239 }
239240 }
240241
241- public String name () {
242+ String name () {
242243 Pattern pattern = Pattern .compile ("^https?://[\\ w./-]+/attr/(\\ S*)/value/\\ S*$" );
243244 Matcher matcher = pattern .matcher (url );
244245 if (!matcher .find ()) {
245246 throw new RuntimeException ("invalid attributeInstance" );
246247 }
247248 try {
248- return URLDecoder .decode (matcher .group (1 ), StandardCharsets .UTF_8 . name () );
249- } catch (UnsupportedEncodingException | IllegalArgumentException e ) {
249+ return URLDecoder .decode (matcher .group (1 ), StandardCharsets .UTF_8 );
250+ } catch (IllegalArgumentException e ) {
250251 throw new RuntimeException ("invalid attributeInstance" , e );
251252 }
252253 }
253254 }
254255
255- public static class KeyAccessGrant {
256+ static class KeyAccessGrant {
256257 public Attribute attr ;
257258 public List <String > kases ;
258259
@@ -295,11 +296,11 @@ public void addAllGrants(AttributeValueFQN fqn, List<KeyAccessServer> gs, Attrib
295296 }
296297 }
297298
298- public KeyAccessGrant byAttribute (AttributeValueFQN fqn ) {
299+ KeyAccessGrant byAttribute (AttributeValueFQN fqn ) {
299300 return grants .get (fqn .key );
300301 }
301302
302- public List <KeySplitStep > plan (List <String > defaultKas , Supplier <String > genSplitID )
303+ @ Nonnull List <KeySplitStep > plan (List <String > defaultKas , Supplier <String > genSplitID )
303304 throws AutoConfigureException {
304305 AttributeBooleanExpression b = constructAttributeBoolean ();
305306 BooleanKeyExpression k = insertKeysForAttribute (b );
@@ -311,17 +312,7 @@ public List<KeySplitStep> plan(List<String> defaultKas, Supplier<String> genSpli
311312 int l = k .size ();
312313 if (l == 0 ) {
313314 // default behavior: split key across all default KAS
314- if (defaultKas .isEmpty ()) {
315- throw new AutoConfigureException ("no default KAS specified; required for grantless plans" );
316- } else if (defaultKas .size () == 1 ) {
317- return Collections .singletonList (new KeySplitStep (defaultKas .get (0 ), "" ));
318- } else {
319- List <KeySplitStep > result = new ArrayList <>();
320- for (String kas : defaultKas ) {
321- result .add (new KeySplitStep (kas , genSplitID .get ()));
322- }
323- return result ;
324- }
315+ return generatePlanFromDefaultKases (defaultKas , genSplitID );
325316 }
326317
327318 List <KeySplitStep > steps = new ArrayList <>();
@@ -334,6 +325,20 @@ public List<KeySplitStep> plan(List<String> defaultKas, Supplier<String> genSpli
334325 return steps ;
335326 }
336327
328+ static List <KeySplitStep > generatePlanFromDefaultKases (List <String > defaultKas , Supplier <String > genSplitID ) {
329+ if (defaultKas .isEmpty ()) {
330+ throw new AutoConfigureException ("no default KAS specified; required for grantless plans" );
331+ } else if (defaultKas .size () == 1 ) {
332+ return Collections .singletonList (new KeySplitStep (defaultKas .get (0 ), "" ));
333+ } else {
334+ List <KeySplitStep > result = new ArrayList <>();
335+ for (String kas : defaultKas ) {
336+ result .add (new KeySplitStep (kas , genSplitID .get ()));
337+ }
338+ return result ;
339+ }
340+ }
341+
337342 BooleanKeyExpression insertKeysForAttribute (AttributeBooleanExpression e ) throws AutoConfigureException {
338343 List <KeyClause > kcs = new ArrayList <>(e .must .size ());
339344
@@ -348,6 +353,7 @@ BooleanKeyExpression insertKeysForAttribute(AttributeBooleanExpression e) throws
348353
349354 List <String > kases = grant .kases ;
350355 if (kases .isEmpty ()) {
356+ // TODO: replace this with a reference to the base key
351357 kases = List .of (RuleType .EMPTY_TERM );
352358 }
353359
@@ -368,6 +374,13 @@ BooleanKeyExpression insertKeysForAttribute(AttributeBooleanExpression e) throws
368374 return new BooleanKeyExpression (kcs );
369375 }
370376
377+ /**
378+ * Constructs an AttributeBooleanExpression from the policy, splitting each attribute
379+ * into its own clause. Each clause contains the attribute definition and a list of
380+ * values.
381+ * @return
382+ * @throws AutoConfigureException
383+ */
371384 AttributeBooleanExpression constructAttributeBoolean () throws AutoConfigureException {
372385 Map <String , SingleAttributeClause > prefixes = new HashMap <>();
373386 List <String > sortedPrefixes = new ArrayList <>();
@@ -378,7 +391,7 @@ AttributeBooleanExpression constructAttributeBoolean() throws AutoConfigureExcep
378391 clause .values .add (aP );
379392 } else if (byAttribute (aP ) != null ) {
380393 var x = new SingleAttributeClause (byAttribute (aP ).attr ,
381- new ArrayList <AttributeValueFQN >(Arrays .asList (aP )));
394+ new ArrayList <>(Arrays .asList (aP )));
382395 prefixes .put (a .getKey (), x );
383396 sortedPrefixes .add (a .getKey ());
384397 }
@@ -391,39 +404,6 @@ AttributeBooleanExpression constructAttributeBoolean() throws AutoConfigureExcep
391404 return new AttributeBooleanExpression (must );
392405 }
393406
394- static class AttributeMapping {
395-
396- private Map <AttributeNameFQN , Attribute > dict ;
397-
398- public AttributeMapping () {
399- this .dict = new HashMap <>();
400- }
401-
402- public void put (Attribute ad ) throws AutoConfigureException {
403- if (this .dict == null ) {
404- this .dict = new HashMap <>();
405- }
406-
407- AttributeNameFQN prefix = new AttributeNameFQN (ad .getFqn ());
408-
409- if (this .dict .containsKey (prefix )) {
410- throw new AutoConfigureException ("Attribute prefix already found: [" + prefix .toString () + "]" );
411- }
412-
413- this .dict .put (prefix , ad );
414- }
415-
416- public Attribute get (AttributeNameFQN prefix ) throws AutoConfigureException {
417- Attribute ad = this .dict .get (prefix );
418- if (ad == null ) {
419- throw new AutoConfigureException ("Unknown attribute type: [" + prefix .toString () + "], not in ["
420- + this .dict .keySet ().toString () + "]" );
421- }
422- return ad ;
423- }
424-
425- }
426-
427407 static class SingleAttributeClause {
428408
429409 private Attribute def ;
@@ -435,9 +415,9 @@ public SingleAttributeClause(Attribute def, List<AttributeValueFQN> values) {
435415 }
436416 }
437417
438- class AttributeBooleanExpression {
418+ static class AttributeBooleanExpression {
439419
440- private List <SingleAttributeClause > must ;
420+ private final List <SingleAttributeClause > must ;
441421
442422 public AttributeBooleanExpression (List <SingleAttributeClause > must ) {
443423 this .must = must ;
@@ -478,7 +458,7 @@ public String toString() {
478458
479459 }
480460
481- public class PublicKeyInfo {
461+ public static class PublicKeyInfo {
482462 private String kas ;
483463
484464 public PublicKeyInfo (String kas ) {
@@ -494,9 +474,9 @@ public void setKas(String kas) {
494474 }
495475 }
496476
497- public class KeyClause {
498- private String operator ;
499- private List <PublicKeyInfo > values ;
477+ public static class KeyClause {
478+ private final String operator ;
479+ private final List <PublicKeyInfo > values ;
500480
501481 public KeyClause (String operator , List <PublicKeyInfo > values ) {
502482 this .operator = operator ;
@@ -531,8 +511,8 @@ public String toString() {
531511 }
532512 }
533513
534- public class BooleanKeyExpression {
535- private List <KeyClause > values ;
514+ public static class BooleanKeyExpression {
515+ private final List <KeyClause > values ;
536516
537517 public BooleanKeyExpression (List <KeyClause > values ) {
538518 this .values = values ;
@@ -612,7 +592,7 @@ public Disjunction sortedNoDupes(List<PublicKeyInfo> l) {
612592
613593 }
614594
615- class Disjunction extends ArrayList <String > {
595+ static class Disjunction extends ArrayList <String > {
616596
617597 public boolean less (Disjunction r ) {
618598 int m = Math .min (this .size (), r .size ());
0 commit comments