Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@

# Ignore Gradle build output directory
build


.idea
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@

import com.contentgrid.opa.client.api.CompileApi;
import com.contentgrid.opa.client.api.CompileApi.PartialEvaluationRequest;
import com.contentgrid.opa.rego.ast.Query;
import com.contentgrid.opa.client.api.DataApi;
import com.contentgrid.opa.client.api.DataApi.GetDataResponse;
import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse;
import com.contentgrid.opa.client.rest.http.HttpStatusException;
import com.contentgrid.opa.rego.ast.Expression;
import com.contentgrid.opa.rego.ast.Query;
import com.contentgrid.opa.rego.ast.Term;
import com.contentgrid.opa.rego.ast.Term.Ref;
import com.contentgrid.opa.client.api.DataApi;
import com.contentgrid.opa.client.api.DataApi.GetDataResponse;
import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse;
import com.contentgrid.opa.rego.ast.Term.Text;
import com.contentgrid.opa.rego.ast.Term.Var;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
Expand All @@ -40,12 +42,12 @@
@Testcontainers
class OpaClientIntegrationTests {

private static final DockerImageName OPA_IMAGE = DockerImageName.parse("openpolicyagent/opa:0.70.0");
private static final DockerImageName OPA_IMAGE = DockerImageName.parse("openpolicyagent/opa:1.9.0");
private static final int OPA_EXPOSED_PORT = 8181;

@Container
private static final GenericContainer<?> opaContainer = new GenericContainer<>(OPA_IMAGE)
.withCommand(String.format("run --server --addr :%d", OPA_EXPOSED_PORT))
.withCommand(String.format("run --server --addr :%d --v0-compatible", OPA_EXPOSED_PORT))
.withExposedPorts(OPA_EXPOSED_PORT)
.waitingFor(Wait.forHttp("/"));

Expand All @@ -68,8 +70,8 @@ void opaIsRunningInDocker() {
@Nested
class PolicyApiTests {

private static final String PATH_EXAMPLE_1 = "fixtures/openpolicyagent.org/docs/policy/policies-example-1.txt";
private static final String PATH_EXAMPLE_2 = "fixtures/openpolicyagent.org/docs/policy/policies-example-2.txt";
private static final String PATH_EXAMPLE_1 = "fixtures/openpolicyagent.org/docs/policy/policies-example-1.rego";
private static final String PATH_EXAMPLE_2 = "fixtures/openpolicyagent.org/docs/policy/policies-example-2.rego";

@Test
@Order(1)
Expand Down Expand Up @@ -195,7 +197,7 @@ void adhocQuery() throws IOException {
@Nested
class CompileApiTests {

public static final String POLICY_PATH = "fixtures/openpolicyagent.org/docs/compile/compile-api-policy.txt";
public static final String POLICY_PATH = "fixtures/openpolicyagent.org/docs/compile/compile-api-policy.rego";

@Test
void unknownInputX_largerThan0() {
Expand Down Expand Up @@ -284,6 +286,76 @@ void compileExample() {
})));
}

@Test
void abacExample() {
opaClient.upsertPolicy("abac-example", loadResourceAsString(
"fixtures/openpolicyagent.org/docs/compile/abac-policy.rego")).join();

var request = new PartialEvaluationRequest(
"data.abac.example.allow == true",
Map.of("request",
Map.of("headers", Map.of("content-type", "application/json"),
"method", "GET",
"path", List.of("tests")
),
"auth", Map.of(
"authenticated", true,
"principal", Map.of(
"kind", "user",
"contentgrid:att1", List.of("att1v1", "att1v2"),
"contentgrid:att2", List.of("att2v1", "att2v2")
)
)
), List.of("input.entity"));

var result = opaClient.compile(request).join();
assertThat(result).isNotNull();
assertThat(result.getResult()).isNotNull();

assertThat(result.getResult().getQueries())
.isNotNull()
// 4 queries are generated, because there are 4 combinations of the 2 attributes in the policy
.hasSize(4)
.allSatisfy(
query -> assertThat(query)
// There are 2 expressions per query, one for every user attribute in the policy
.hasSize(2)
.allSatisfy(expr -> {
// each expression has 3 terms (the 'eq' operator, the attribute value and the input value)
assertThat(expr.getTerms())
.hasSize(3)
.anySatisfy(
term -> {
assertThat(term).isInstanceOfSatisfying(Ref.class, ref -> {
assertThat(ref.getValue()).singleElement().satisfies(
t -> assertThat(t).hasToString("eq")
);
});
}
);
})
)
.anySatisfy(query -> {
assertThat(query).anySatisfy(
expr -> assertThat(expr.getTerms())
.isEqualTo(List.of(
new Ref(List.of(new Var("eq"))),
new Text("att1v1"),
new Ref(List.of(
new Var("input"),
new Text("entity"),
new Text("a")
)
)
)

)
);

})
;
}

@Test
void example_alwaysTrue() {
opaClient.upsertPolicy("compile-example", loadResourceAsString(POLICY_PATH)).join();
Expand Down Expand Up @@ -343,7 +415,7 @@ class Scenarios {
*/
@Test
void partialEval_getApiDocuments() {
final String POLICY_PATH = "fixtures/scenarios/api-documents-policy.txt";
final String POLICY_PATH = "fixtures/scenarios/api-documents-policy.rego";
opaClient.upsertPolicy("test", loadResourceAsString(POLICY_PATH)).join();

var result = opaClient.compile(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.contentgrid.opa.client.api;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse;
import com.contentgrid.opa.rego.ast.Term;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.junit.jupiter.api.Test;

class PolicyApiTest {

@Test
void testPoliciesResponseObjectMapping() {
var objectMapper = JsonMapper.builder()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build()
.registerModule(new JavaTimeModule());

// read listpoliciesresponse.json into ListPoliciesResponse
try (var is = getClass().getClassLoader().getResourceAsStream(
"com/contentgrid/opa/client/api/policyapi/listpoliciesresponse.json")) {
var response = objectMapper.readValue(is, ListPoliciesResponse.class);
assertNotNull(response);
assertThat(response.getResult().get(2).getAst().getRules().get(1).getBody()).singleElement().satisfies(expression -> {
assertThat(expression.getTerms()).singleElement().isInstanceOfSatisfying(Term.Bool.class, boolTerm -> {
assertThat(boolTerm.getValue()).isTrue();
});
});
} catch (Exception e) {
fail("Failed to deserialize ListPoliciesResponse", e);
}
}

}
Loading