Skip to content

Commit e548e4d

Browse files
committed
Refactor tests for better readability.
Change-Id: Icfd0bc24c1694f220bcbffc6cde41462c59119c4
1 parent a43dd7c commit e548e4d

File tree

2 files changed

+160
-77
lines changed

2 files changed

+160
-77
lines changed

cab-token-generator/java/com/google/auth/credentialaccessboundary/ClientSideCredentialAccessBoundaryFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ public void run() {
473473
/**
474474
* Serializes a {@link CredentialAccessBoundary} object into Protobuf wire format.
475475
*/
476-
private byte[] serializeCredentialAccessBoundary(
476+
@VisibleForTesting
477+
byte[] serializeCredentialAccessBoundary(
477478
CredentialAccessBoundary credentialAccessBoundary)
478479
throws CelValidationException {
479480
List<AccessBoundaryRule> rules =

cab-token-generator/javatests/com/google/auth/credentialaccessboundary/ClientSideCredentialAccessBoundaryFactoryTest.java

Lines changed: 158 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import static com.google.auth.oauth2.OAuth2Utils.TOKEN_EXCHANGE_URL_FORMAT;
3535
import static org.junit.Assert.assertEquals;
36+
import static org.junit.Assert.assertFalse;
3637
import static org.junit.Assert.assertNotNull;
3738
import static org.junit.Assert.assertThrows;
3839
import static org.junit.Assert.assertTrue;
@@ -589,6 +590,40 @@ private static void triggerConcurrentRefresh(
589590
}
590591
}
591592

593+
private static class CabToken {
594+
String intermediateToken;
595+
String encryptedRestriction;
596+
597+
CabToken(String intermediateToken, String encryptedRestriction) {
598+
this.intermediateToken = intermediateToken;
599+
this.encryptedRestriction = encryptedRestriction;
600+
}
601+
}
602+
603+
private static CabToken parseCabToken(AccessToken token) throws Exception {
604+
String[] parts = token.getTokenValue().split("\\.");
605+
assertEquals(parts.length, 2);
606+
607+
return new CabToken(parts[0], parts[1]);
608+
}
609+
610+
private static ClientSideAccessBoundary decryptRestriction(String restriction,
611+
String sessionKey)
612+
throws Exception {
613+
byte[] rawKey = Base64.getDecoder().decode(sessionKey);
614+
615+
KeysetHandle keysetHandle = TinkProtoKeysetFormat.parseKeyset(
616+
rawKey, InsecureSecretKeyAccess.get());
617+
618+
Aead aead =
619+
keysetHandle.getPrimitive(RegistryConfiguration.get(), Aead.class);
620+
byte[] rawRestrictions =
621+
aead.decrypt(Base64.getUrlDecoder().decode(restriction),
622+
/*associatedData=*/new byte[0]);
623+
624+
return ClientSideAccessBoundary.parseFrom(rawRestrictions);
625+
}
626+
592627
@Test
593628
public void generateToken_withAvailablityCondition_success() throws Exception {
594629
MockStsTransportFactory transportFactory = new MockStsTransportFactory();
@@ -610,56 +645,42 @@ public void generateToken_withAvailablityCondition_success() throws Exception {
610645
cabBuilder
611646
.addRule(
612647
CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
613-
.setAvailableResource("//storage.googleapis.com/projects/"
614-
+ "_/buckets/example-bucket")
615-
.setAvailablePermissions(
616-
ImmutableList.of("inRole:roles/storage.objectViewer"))
648+
.setAvailableResource("resource")
649+
.setAvailablePermissions(ImmutableList.of("role1", "role2"))
617650
.setAvailabilityCondition(
618651
CredentialAccessBoundary.AccessBoundaryRule
619652
.AvailabilityCondition.newBuilder()
620-
.setExpression(
621-
"resource.name.startsWith('projects/_/"
622-
+ "buckets/example-bucket/objects/customer-a')")
653+
.setExpression("a == b")
623654
.build())
624655
.build())
625656
.build();
626657

627658
AccessToken token = factory.generateToken(accessBoundary);
628659

629-
String[] parts = token.getTokenValue().split("\\.");
630-
assertEquals(parts.length, 2);
631-
assertEquals(parts[0], "accessToken");
660+
CabToken cabToken = parseCabToken(token);
661+
assertEquals(cabToken.intermediateToken, "accessToken");
632662

633-
byte[] rawKey = Base64.getDecoder().decode(
663+
// Checks the encrypted restriction is the correct proto format of the
664+
// CredentialAccessBoundary
665+
ClientSideAccessBoundary clientSideAccessBoundary = decryptRestriction(
666+
cabToken.encryptedRestriction,
634667
transportFactory.transport.getAccessBoundarySessionKey());
635-
636-
KeysetHandle keysetHandle = TinkProtoKeysetFormat.parseKeyset(
637-
rawKey, InsecureSecretKeyAccess.get());
638-
639-
Aead aead =
640-
keysetHandle.getPrimitive(RegistryConfiguration.get(), Aead.class);
641-
byte[] rawRestrictions =
642-
aead.decrypt(Base64.getUrlDecoder().decode(parts[1]), new byte[0]);
643-
ClientSideAccessBoundary clientSideAccessBoundary =
644-
ClientSideAccessBoundary.parseFrom(rawRestrictions);
645668
assertEquals(clientSideAccessBoundary.getAccessBoundaryRulesCount(), 1);
669+
646670
ClientSideAccessBoundaryRule rule =
647671
clientSideAccessBoundary.getAccessBoundaryRules(0);
648-
assertEquals(rule.getAvailableResource(),
649-
"//storage.googleapis.com/projects/_/buckets/example-bucket");
650-
assertEquals(rule.getAvailablePermissions(0),
651-
"inRole:roles/storage.objectViewer");
672+
673+
// Available resource and available permission should be the exact same as
674+
// in original format
675+
assertEquals(rule.getAvailableResource(), "resource");
676+
assertEquals(rule.getAvailablePermissionsList(),
677+
ImmutableList.of("role1", "role2"));
678+
679+
// Availablity condition should be in the correct compiled proto format
652680
Expr expr = rule.getCompiledAvailabilityCondition();
653-
assertEquals(expr.getCallExpr()
654-
.getTarget()
655-
.getSelectExpr()
656-
.getOperand()
657-
.getIdentExpr()
658-
.getName(),
659-
"resource");
660-
assertEquals(expr.getCallExpr().getFunction(), "startsWith");
661-
assertEquals(expr.getCallExpr().getArgs(0).getConstExpr().getStringValue(),
662-
"projects/_/buckets/example-bucket/objects/customer-a");
681+
assertEquals(expr.getCallExpr().getFunction(), "_==_");
682+
assertEquals(expr.getCallExpr().getArgs(0).getIdentExpr().getName(), "a");
683+
assertEquals(expr.getCallExpr().getArgs(1).getIdentExpr().getName(), "b");
663684
}
664685

665686
@Test
@@ -681,42 +702,102 @@ public void generateToken_withoutAvailabilityCondition_success() throws Exceptio
681702
CredentialAccessBoundary.newBuilder();
682703
CredentialAccessBoundary accessBoundary =
683704
cabBuilder
684-
.addRule(
685-
CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
686-
.setAvailableResource("//storage.googleapis.com/projects/"
687-
+ "_/buckets/example-bucket")
688-
.setAvailablePermissions(
689-
ImmutableList.of("inRole:roles/storage.objectViewer"))
690-
.build())
705+
.addRule(CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
706+
.setAvailableResource("resource")
707+
.setAvailablePermissions(ImmutableList.of("role"))
708+
.build())
691709
.build();
692710

693711
AccessToken token = factory.generateToken(accessBoundary);
694712

695-
String[] parts = token.getTokenValue().split("\\.");
696-
assertEquals(parts.length, 2);
697-
assertEquals(parts[0], "accessToken");
713+
CabToken cabToken = parseCabToken(token);
714+
assertEquals(cabToken.intermediateToken, "accessToken");
698715

699-
byte[] rawKey = Base64.getDecoder().decode(
716+
// Checks the encrypted restriction is the correct proto format of the
717+
// CredentialAccessBoundary
718+
ClientSideAccessBoundary clientSideAccessBoundary = decryptRestriction(
719+
cabToken.encryptedRestriction,
700720
transportFactory.transport.getAccessBoundarySessionKey());
701-
702-
KeysetHandle keysetHandle = TinkProtoKeysetFormat.parseKeyset(
703-
rawKey, InsecureSecretKeyAccess.get());
704-
705-
Aead aead =
706-
keysetHandle.getPrimitive(RegistryConfiguration.get(), Aead.class);
707-
byte[] rawRestrictions =
708-
aead.decrypt(Base64.getUrlDecoder().decode(parts[1]), new byte[0]);
709-
ClientSideAccessBoundary clientSideAccessBoundary =
710-
ClientSideAccessBoundary.parseFrom(rawRestrictions);
711721
assertEquals(clientSideAccessBoundary.getAccessBoundaryRulesCount(), 1);
722+
712723
ClientSideAccessBoundaryRule rule =
713724
clientSideAccessBoundary.getAccessBoundaryRules(0);
714-
assertEquals(rule.getAvailableResource(),
715-
"//storage.googleapis.com/projects/_/buckets/example-bucket");
716-
assertEquals(rule.getAvailablePermissions(0),
717-
"inRole:roles/storage.objectViewer");
718-
assertTrue(rule.getCompiledAvailabilityCondition().equals(
719-
Expr.getDefaultInstance()));
725+
726+
// Available resource and available permission should be the exact same as
727+
// in original format
728+
assertEquals(rule.getAvailableResource(), "resource");
729+
assertEquals(rule.getAvailablePermissionsList(), ImmutableList.of("role"));
730+
731+
// Availablity condition should be empty since it's not provided
732+
assertFalse(rule.hasCompiledAvailabilityCondition());
733+
}
734+
735+
@Test
736+
public void generateToken_withMultipleRules_success() throws Exception {
737+
MockStsTransportFactory transportFactory = new MockStsTransportFactory();
738+
transportFactory.transport.setReturnAccessBoundarySessionKey(true);
739+
740+
ClientSideCredentialAccessBoundaryFactory.Builder builder =
741+
ClientSideCredentialAccessBoundaryFactory.newBuilder();
742+
743+
ClientSideCredentialAccessBoundaryFactory factory =
744+
builder
745+
.setSourceCredential(getServiceAccountSourceCredentials(
746+
mockTokenServerTransportFactory))
747+
.setHttpTransportFactory(transportFactory)
748+
.build();
749+
750+
CredentialAccessBoundary.Builder cabBuilder =
751+
CredentialAccessBoundary.newBuilder();
752+
CredentialAccessBoundary accessBoundary =
753+
cabBuilder
754+
.addRule(CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
755+
.setAvailableResource("resource1")
756+
.setAvailablePermissions(
757+
ImmutableList.of("role1-1", "role1-2"))
758+
.setAvailabilityCondition(
759+
CredentialAccessBoundary.AccessBoundaryRule
760+
.AvailabilityCondition.newBuilder()
761+
.setExpression("a == b")
762+
.build())
763+
.build())
764+
.addRule(CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
765+
.setAvailableResource("resource")
766+
.setAvailablePermissions(ImmutableList.of("role2"))
767+
.build())
768+
.build();
769+
770+
AccessToken token = factory.generateToken(accessBoundary);
771+
772+
CabToken cabToken = parseCabToken(token);
773+
assertEquals(cabToken.intermediateToken, "accessToken");
774+
775+
// Checks the encrypted restriction is the correct proto format of the
776+
// CredentialAccessBoundary
777+
ClientSideAccessBoundary clientSideAccessBoundary = decryptRestriction(
778+
cabToken.encryptedRestriction,
779+
transportFactory.transport.getAccessBoundarySessionKey());
780+
assertEquals(clientSideAccessBoundary.getAccessBoundaryRulesCount(), 2);
781+
782+
// Checks the first rule
783+
ClientSideAccessBoundaryRule rule1 =
784+
clientSideAccessBoundary.getAccessBoundaryRules(0);
785+
assertEquals(rule1.getAvailableResource(), "resource1");
786+
assertEquals(rule1.getAvailablePermissionsList(),
787+
ImmutableList.of("role1-1", "role1-2"));
788+
789+
Expr expr = rule1.getCompiledAvailabilityCondition();
790+
assertEquals(expr.getCallExpr().getFunction(), "_==_");
791+
assertEquals(expr.getCallExpr().getArgs(0).getIdentExpr().getName(), "a");
792+
assertEquals(expr.getCallExpr().getArgs(1).getIdentExpr().getName(), "b");
793+
794+
// Checks the second rule
795+
ClientSideAccessBoundaryRule rule2 =
796+
clientSideAccessBoundary.getAccessBoundaryRules(1);
797+
assertEquals(rule2.getAvailableResource(), "resource");
798+
assertEquals(rule2.getAvailablePermissionsList(),
799+
ImmutableList.of("role2"));
800+
assertFalse(rule2.hasCompiledAvailabilityCondition());
720801
}
721802

722803
@Test
@@ -738,20 +819,21 @@ public void generateToken_withInvalidAvailabilityCondition_failure() throws Exce
738819
CredentialAccessBoundary.newBuilder();
739820
CredentialAccessBoundary accessBoundary =
740821
cabBuilder
741-
.addRule(
742-
CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
743-
.setAvailableResource("//storage.googleapis.com/projects/"
744-
+ "_/buckets/example-bucket")
745-
.setAvailablePermissions(
746-
ImmutableList.of("inRole:roles/storage.objectViewer"))
747-
.setAvailabilityCondition(
748-
CredentialAccessBoundary.AccessBoundaryRule
749-
.AvailabilityCondition.newBuilder()
750-
.setExpression(
751-
"resource.name.startsWith('projects/_/"
752-
+ "buckets/example-bucket/objects/customer-a'")
753-
.build())
754-
.build())
822+
.addRule(CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
823+
.setAvailableResource(
824+
"//storage.googleapis.com/projects/"
825+
+ "_/buckets/example-bucket")
826+
.setAvailablePermissions(ImmutableList.of(
827+
"inRole:roles/storage.objectViewer"))
828+
.setAvailabilityCondition(
829+
CredentialAccessBoundary.AccessBoundaryRule
830+
.AvailabilityCondition.newBuilder()
831+
.setExpression(
832+
"resource.name.startsWith('projects/_/"
833+
+ "buckets/example-bucket/objects/" +
834+
"customer-a'") // No closing bracket
835+
.build())
836+
.build())
755837
.build();
756838

757839
assertThrows(CelValidationException.class,

0 commit comments

Comments
 (0)