1313
1414import com .connectrpc .ResponseMessage ;
1515import com .connectrpc .UnaryBlockingCall ;
16+ import io .opentdf .platform .policy .Algorithm ;
1617import io .opentdf .platform .policy .Attribute ;
1718import io .opentdf .platform .policy .AttributeRuleTypeEnum ;
1819import io .opentdf .platform .policy .KasPublicKey ;
2122import io .opentdf .platform .policy .KeyAccessServer ;
2223import io .opentdf .platform .policy .Namespace ;
2324import io .opentdf .platform .policy .PublicKey ;
25+ import io .opentdf .platform .policy .SimpleKasKey ;
26+ import io .opentdf .platform .policy .SimpleKasPublicKey ;
2427import io .opentdf .platform .policy .Value ;
2528import io .opentdf .platform .policy .attributes .AttributesServiceClient ;
2629import io .opentdf .platform .policy .attributes .GetAttributeValuesByFqnsRequest ;
3134import io .opentdf .platform .sdk .Autoconfigure .KeySplitStep ;
3235import io .opentdf .platform .sdk .Autoconfigure .Granter ;
3336
37+ import org .assertj .core .api .AtomicIntegerArrayAssert ;
3438import org .junit .jupiter .api .BeforeAll ;
3539import org .junit .jupiter .api .Test ;
3640import org .mockito .Mockito ;
3943import java .util .Collections ;
4044import java .util .HashSet ;
4145import java .util .List ;
46+ import java .util .Objects ;
4247import java .util .Optional ;
4348import java .util .Set ;
49+ import java .util .concurrent .atomic .AtomicInteger ;
4450import java .util .stream .Collectors ;
4551import java .util .regex .Matcher ;
4652import java .util .regex .Pattern ;
@@ -57,6 +63,16 @@ public class AutoconfigureTest {
5763 public static final String SPECIFIED_KAS = "https://attr.kas.com/" ;
5864 public static final String EVEN_MORE_SPECIFIC_KAS = "https://value.kas.com/" ;
5965 private static final String NAMESPACE_KAS = "https://namespace.kas.com/" ;
66+ private static final SimpleKasKey NAMESPACE_KAS_KEY = SimpleKasKey .newBuilder ().setKasUri ("https://mapped.example.com" ).setKasId ("mapped" ).setPublicKey (
67+ SimpleKasPublicKey .newBuilder ().setAlgorithm (Algorithm .ALGORITHM_EC_P521 ).setPem ("namespacekey" ).setKid ("namespacekeykid" ).build ()
68+ ).build ();
69+ private static final SimpleKasKey ATTRIBUTE_KEY = SimpleKasKey .newBuilder ().setKasUri ("https://mapped.example.com" ).setKasId ("mapped" ).setPublicKey (
70+ SimpleKasPublicKey .newBuilder ().setAlgorithm (Algorithm .ALGORITHM_EC_P521 ).setPem ("attrpem" ).setKid ("attrkeykid" ).build ()
71+ ).build ();
72+ private static final SimpleKasKey VALUE_KEY = SimpleKasKey .newBuilder ().setKasUri ("https://mapped.example.com" ).setKasId ("mapped" ).setPublicKey (
73+ SimpleKasPublicKey .newBuilder ().setAlgorithm (Algorithm .ALGORITHM_EC_P521 ).setPem ("valuepem" ).setKid ("valuekeykid" ).build ()
74+ ).build ();
75+ private static Autoconfigure .AttributeNameFQN UNMAPPED ;
6076 private static Autoconfigure .AttributeNameFQN SPKSPECKED ;
6177 private static Autoconfigure .AttributeNameFQN SPKUNSPECKED ;
6278
@@ -65,6 +81,8 @@ public class AutoconfigureTest {
6581 private static Autoconfigure .AttributeNameFQN REL ;
6682 private static Autoconfigure .AttributeNameFQN UNSPECKED ;
6783 private static Autoconfigure .AttributeNameFQN SPECKED ;
84+ private static Autoconfigure .AttributeNameFQN MAPPED ;
85+ private static Autoconfigure .AttributeNameFQN SPKMAPPED ;
6886
6987 private static Autoconfigure .AttributeValueFQN clsA ;
7088 private static Autoconfigure .AttributeValueFQN clsS ;
@@ -85,6 +103,9 @@ public class AutoconfigureTest {
85103 private static Autoconfigure .AttributeValueFQN spk2spk2uns ;
86104 private static Autoconfigure .AttributeValueFQN spk2spk2spk ;
87105
106+ private static Autoconfigure .AttributeValueFQN mp2uns2uns ;
107+ private static Autoconfigure .AttributeValueFQN mp2uns2mp ;
108+
88109 @ BeforeAll
89110 public static void setup () throws AutoConfigureException {
90111 // Initialize the FQNs (Fully Qualified Names)
@@ -93,8 +114,11 @@ public static void setup() throws AutoConfigureException {
93114 REL = new Autoconfigure .AttributeNameFQN ("https://virtru.com/attr/Releasable%20To" );
94115 UNSPECKED = new Autoconfigure .AttributeNameFQN ("https://other.com/attr/unspecified" );
95116 SPECKED = new Autoconfigure .AttributeNameFQN ("https://other.com/attr/specified" );
117+ MAPPED = new Autoconfigure .AttributeNameFQN ("https://other.com/attr/mapped" );
118+ UNMAPPED = new Autoconfigure .AttributeNameFQN ("https://mapped.com/attr/unspecified" );
96119 SPKUNSPECKED = new Autoconfigure .AttributeNameFQN ("https://hasgrants.com/attr/unspecified" );
97120 SPKSPECKED = new Autoconfigure .AttributeNameFQN ("https://hasgrants.com/attr/specified" );
121+ SPKMAPPED = new Autoconfigure .AttributeNameFQN ("https://hasgrants.com/attr/mapped" );
98122
99123 clsA = new Autoconfigure .AttributeValueFQN ("https://virtru.com/attr/Classification/value/Allowed" );
100124 clsS = new Autoconfigure .AttributeValueFQN ("https://virtru.com/attr/Classification/value/Secret" );
@@ -118,6 +142,9 @@ public static void setup() throws AutoConfigureException {
118142 spk2uns2spk = new Autoconfigure .AttributeValueFQN ("https://hasgrants.com/attr/unspecified/value/specked" );
119143 spk2spk2uns = new Autoconfigure .AttributeValueFQN ("https://hasgrants.com/attr/specified/value/unspecked" );
120144 spk2spk2spk = new Autoconfigure .AttributeValueFQN ("https://hasgrants.com/attr/specified/value/specked" );
145+
146+ mp2uns2uns = new Autoconfigure .AttributeValueFQN ("https://mapped.com/attr/unspecified/value/unspecked" );
147+ mp2uns2mp = new Autoconfigure .AttributeValueFQN ("https://mapped.com/attr/unspecified/value/mapped" );
121148 }
122149
123150 private static String spongeCase (String s ) {
@@ -182,6 +209,7 @@ private Attribute mockAttributeFor(Autoconfigure.AttributeNameFQN fqn) {
182209 Namespace ns1 = Namespace .newBuilder ().setId ("v" ).setName ("virtru.com" ).setFqn ("https://virtru.com" ).build ();
183210 Namespace ns2 = Namespace .newBuilder ().setId ("o" ).setName ("other.com" ).setFqn ("https://other.com" ).build ();
184211 Namespace ns3 = Namespace .newBuilder ().setId ("h" ).setName ("hasgrants.com" ).addGrants (KeyAccessServer .newBuilder ().setUri (NAMESPACE_KAS ).build ()).setFqn ("https://hasgrants.com" ).build ();
212+ Namespace ns4 = Namespace .newBuilder ().setId ("m" ).setName ("mapped.com" ).addKasKeys (NAMESPACE_KAS_KEY ).build ();
185213
186214 String key = fqn .getKey ();
187215 if (key .equals (CLS .getKey ())) {
@@ -217,6 +245,17 @@ private Attribute mockAttributeFor(Autoconfigure.AttributeNameFQN fqn) {
217245 .setName ("unspecified" ).setRule (AttributeRuleTypeEnum .ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF )
218246 .setName (fqn .toString ())
219247 .build ();
248+ } else if (key .equals (MAPPED .getKey ())) {
249+ return Attribute .newBuilder ().setId (MAPPED .getKey ()).setNamespace (ns4 )
250+ .setName ("mapped attribute" ).setRule (AttributeRuleTypeEnum .ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF )
251+ .setKasKeys (0 , ATTRIBUTE_KEY )
252+ .setName (fqn .toString ())
253+ .build ();
254+ } else if (key .equals (UNMAPPED .getKey ())) {
255+ return Attribute .newBuilder ().setId (UNMAPPED .getKey ()).setNamespace (ns4 )
256+ .setName ("unmapped attribute" ).setRule (AttributeRuleTypeEnum .ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF )
257+ .setName (fqn .toString ())
258+ .build ();
220259 }
221260
222261 throw new IllegalArgumentException ("Key not recognized: " + key );
@@ -288,7 +327,13 @@ private Value mockValueFor(Autoconfigure.AttributeValueFQN fqn) throws AutoConfi
288327 p = p .toBuilder ().addGrants (KeyAccessServer .newBuilder ().setUri (EVEN_MORE_SPECIFIC_KAS ).build ())
289328 .build ();
290329 }
330+ } else if (Objects .equals (UNMAPPED .getKey (), an .getKey ())) {
331+ if (fqn .value ().equalsIgnoreCase ("mapped" )) {
332+ p = p .toBuilder ().addKasKeys (VALUE_KEY )
333+ .build ();
334+ }
291335 }
336+
292337 return p ;
293338 }
294339
@@ -475,6 +520,26 @@ public void testReasonerConstructAttributeBoolean() {
475520 }
476521 }
477522
523+ @ Test
524+ void testUsingAttributeMappedAtNamespace () {
525+ Granter granter = Autoconfigure .newGranterFromAttributes (new KASKeyCache (), mockValueFor (mp2uns2uns ));
526+ var counter = new AtomicInteger (0 );
527+ var splitPlan = granter .getSplits (Collections .emptyList (), () -> Integer .toString (counter .getAndIncrement ()), () -> Optional .empty ());
528+ assertThat (splitPlan ).isEqualTo (List .of (new KeySplitStep ("https://mapped.example.com" , "" , NAMESPACE_KAS_KEY .getPublicKey ().getKid ())));
529+ }
530+
531+ @ Test
532+ void testUsingAttributeMappedAtMultiplePlaces () {
533+ var attributes = new Value [] { mockValueFor (mp2uns2uns ), mockValueFor (mp2uns2mp ) };
534+ Granter granter = Autoconfigure .newGranterFromAttributes (new KASKeyCache (), attributes );
535+ var counter = new AtomicInteger (0 );
536+ var splitPlan = granter .getSplits (Collections .emptyList (), () -> Integer .toString (counter .getAndIncrement ()), () -> Optional .empty ());
537+ assertThat (splitPlan ).isEqualTo (List .of (
538+ new KeySplitStep (NAMESPACE_KAS_KEY .getKasUri (), "0" , NAMESPACE_KAS_KEY .getPublicKey ().getKid ()),
539+ new KeySplitStep (VALUE_KEY .getKasUri (), "0" , VALUE_KEY .getPublicKey ().getKid ())
540+ ));
541+ }
542+
478543 GetAttributeValuesByFqnsResponse getResponse (GetAttributeValuesByFqnsRequest req ) {
479544 GetAttributeValuesByFqnsResponse .Builder builder = GetAttributeValuesByFqnsResponse .newBuilder ();
480545
0 commit comments