Skip to content
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

Add != #142

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Add != #142

wants to merge 1 commit into from

Conversation

mauromorales
Copy link

Hi, I got referred to your project and I find it quite interesting. Here's my attempt at adding != which seems to be needed for v3. Looking forward to your feedback

relates to #117

Signed-off-by: Mauro Morales <[email protected]>
@mauromorales
Copy link
Author

@lu-zero I saw your post on x, not sure if you're the right person to ping, but maybe you can point me to the right person. Thanks!

@divarvel
Copy link
Contributor

Thanks for your PR!

The general idea is good, but since biscuit blocks are versioned, the new operations cannot be directly added, they need to be checked against the block number (ie a block with version=3 cannot contain a != operator, and conversely, serializing a block that contains this operator must have a minimum version of 4).

Additionally, the samples.json file is copied from the spec https://github.com/biscuit-auth/biscuit/blob/main/samples/current/samples.json and should not be modified directly, as it is kept in sync with biscuit files as well.

@mauromorales
Copy link
Author

@divarvel let me see if I understand correctly, the current implementation is testing against https://github.com/biscuit-auth/biscuit/blob/main/samples/deprecated/v2/samples.json

So for adding != it would need to be a version 3 of the library, and test against https://github.com/biscuit-auth/biscuit/blob/main/samples/current/samples.json

I'll need a bit of further explanation about what is a block of version 3 and a block version 4 are we talking about the same versions than in the samples, or is this a different kind of version?

@Geal
Copy link
Contributor

Geal commented May 18, 2024

@mauromorales thank you for looking into this!

I'll need a bit of further explanation about what is a block of version 3 and a block version 4 are we talking about the same versions than in the samples, or is this a different kind of version?

Biscuit token contain multiple blocks, each one corresponding to one level of attenuation. Each of those blocks holds a version number: https://github.com/biscuit-auth/biscuit/blob/main/schema.proto#L45
That version number indicates the presence of newer features (ex: new ways to check in datalog), to make sure that older implementations cannot accept newer tokens without validating the new features.
From the specification:

Each block contains a version field, indicating at which format version it
was generated. Since a Biscuit implementation at version N can receive a valid
token generated at version N-1, new implementations must be able to recognize
older formats. Moreover, when appending a new block, they cannot convert the
old blocks to the new format (since that would invalidate the signature). So
each block must carry its own version.

  • An implementation must refuse a token containing blocks with a newer format than the range they know.

  • An implementation must refuse a token containing blocks with an older format than the range they know.

  • An implementation may generate blocks with older formats to help with backwards compatibility,
    when possible, especially for biscuit versions that are only additive in terms of features.

  • The lowest supported biscuit version is 3;

  • The highest supported biscuit version is 4;

In general, we make sure that when generating a block, we use the lowest version number possible (if no new features are used, keep a lower number) so that they could still be validated by older versions.

@Geal
Copy link
Contributor

Geal commented May 18, 2024

this is where we check the version when parsing the token:

biscuit-go/converters.go

Lines 64 to 110 in 61386fc

if input.GetVersion() < MinSchemaVersion {
return nil, fmt.Errorf(
"biscuit: failed to convert proto block to token block: block version: %d < library version %d",
input.GetVersion(),
MinSchemaVersion,
)
}
if input.GetVersion() > MaxSchemaVersion {
return nil, fmt.Errorf(
"biscuit: failed to convert proto block to token block: block version: %d > library version %d",
input.GetVersion(),
MaxSchemaVersion,
)
}
switch input.GetVersion() {
case 3:
facts = make(datalog.FactSet, len(input.FactsV2))
rules = make([]datalog.Rule, len(input.RulesV2))
checks = make([]datalog.Check, len(input.ChecksV2))
for i, pbFact := range input.FactsV2 {
f, err := protoFactToTokenFactV2(pbFact)
if err != nil {
return nil, err
}
facts[i] = *f
}
for i, pbRule := range input.RulesV2 {
r, err := protoRuleToTokenRuleV2(pbRule)
if err != nil {
return nil, err
}
rules[i] = *r
}
for i, pbCheck := range input.ChecksV2 {
c, err := protoCheckToTokenCheckV2(pbCheck)
if err != nil {
return nil, err
}
checks[i] = *c
}
default:
return nil, fmt.Errorf("biscuit: failed to convert proto block to token block: unsupported version: %d", input.GetVersion())
}

It looks like this implementation does not minimize the version number when serializing though:

biscuit-go/builder.go

Lines 115 to 122 in 61386fc

return New(b.rng, b.root, b.symbols, &Block{
symbols: b.symbols.SplitOff(b.symbolsStart),
facts: b.facts,
rules: b.rules,
checks: b.checks,
context: b.context,
version: MaxSchemaVersion,
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants