Macaroon schemas and types

77 views
Skip to first unread message

Tony Arcieri

unread,
Dec 23, 2015, 2:23:39 PM12/23/15
to maca...@googlegroups.com
I've been working on an "opinionated" high-level Macaroon in Ruby called Boulangerie:


One of the main features is support for extensible statically typed schemas, using a YAML-based schema language. Here's an example schema:


The types in that schema (Boolean, Binary, and DateTime) are the only ones presently supported by the library, however I just wrote up some initial documentation on these types and some provisional types I'd like to add (barring someone convincing me otherwise):


Aside from URI, they're all simple and constrained.

I'd like to support a List type, which is a comma-delimited list of another type. Without a quoting mechanism (which I was specifically trying to avoid, as escaping bugs are a common source of vulnerabilities) lists will not be supported for all types, e.g. Binary and Lists themselves, and will only work for types whose serializations cannot contain the "," character. A caveat with a list of decimals will end up looking like:

    cid number-in 0,1,2,3,4,5

The goal of this approach is to have a standard syntax and serialization framework where possible, converting serialized caveats to/from native types. It's also designed to keep serialization and syntactic overhead to a minimum.

Happy to hear your thoughts, especially around the provisional types and what ones should be added or removed.

--
Tony Arcieri

Robert Escriva

unread,
Dec 23, 2015, 3:12:55 PM12/23/15
to maca...@googlegroups.com
Hi Tony,

I haven't had time to go through this, but I like the idea of
standardization.

I'd recommend that we simply adopt the convention that first party
caveats must be unique to the project in the first N letters (similar to
how C projects work). It adds a bit of overhead, but is worth allowing
multiple frameworks to develop on top.

I'm still of the belief that it's better to encode structures in the
macaroons proof tree and let the verifier do its thing rather than
shoe-horning a different authorization logic into the caveat language
and effectively turning the verifier into a pass through for that other
language.

Of course, this is just my belief. Taking the "unique caveat prefix"
approach allows both to exist in harmony.

I would also recommend that every framework standardize on caveats of
the form:

expires: %Y-%m-%dT%H:%M:%S

This enables every macaroon to be expired reliably across all
frameworks.

Any thoughts? After the pre-holiday rush I'll give these projects a
proper once-over and give better feedback.

-Robert
> --
> You received this message because you are subscribed to the Google Groups
> "Macaroons" group.
> To unsubscribe from this group and stop receiving emails from it, send an email
> to macaroons+...@googlegroups.com.
> To post to this group, send email to maca...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/
> macaroons/
> CAHOTMV%2Bm0P6kg1CPXtaW8u2oL3v%2BLrVfdKxXxMOAu5q2tPeF1w%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

Martin W. Kirst

unread,
Dec 23, 2015, 3:17:19 PM12/23/15
to maca...@googlegroups.com
Hi,

I understand you want to achieve some kind of standardization regarding the formatting of predicates.
This is a very good idea.
What I'm not getting is the point of "... extensible statically typed schemas ..."
Or what problem you're trying to solve with the yaml schemas?

For a predicate I would expect something like a BNF *1) describing possible contents.
This could also be visualized in fancy rail-road-diagrams, like e.g. on json.org.

Kindly Regards
Martin

*1)

--

Jørn Wildt

unread,
Dec 23, 2015, 3:55:45 PM12/23/15
to maca...@googlegroups.com
"expires: ..." is fine with me, but could we refer to a standard date/time format including/allowing time zone? For instance https://en.wikipedia.org/wiki/ISO_8601 or https://www.ietf.org/rfc/rfc3339.txt (which would be best?). There is guaranteed to be problems with time zone handling if it isn't part of the game from the start.

I'm still of the belief that it's better to encode structures in the
> macaroons proof tree and let the verifier do its thing rather than
> shoe-horning a different authorization logic into the caveat language
> and effectively turning the verifier into a pass through for that other
> language.

Sounds like the proper way to go - except that I don't see how "c in 1,2,3,4" could be encoded otherwise? Or should it simply be 4 different macaroons?

/Jørn

Robert Escriva

unread,
Dec 23, 2015, 4:28:28 PM12/23/15
to maca...@googlegroups.com, Jørn Wildt
I think it best to declare all expires to be utc. This puts the burden on the user to convert to utc, but greatly reduces the complexity of macaroons. Further it guarantees that there is no error in misinterpreting timezones. The ISO standard you listed is merely a constant offset from utc anyway.

The in predicate can be expressed as a disjunction/or predicate across multiple macaroons.
Sent from my phone. Please excuse my brevity.

Tony Arcieri

unread,
Dec 23, 2015, 4:29:10 PM12/23/15
to maca...@googlegroups.com
On Wed, Dec 23, 2015 at 12:17 PM, Martin W. Kirst <x.nit...@gmail.com> wrote:
What I'm not getting is the point of "... extensible statically typed schemas ..."
Or what problem you're trying to solve with the yaml schemas?

I think having standard schemas is critical for interoperability, especially for things like third party caveats. Types allow for standard serializations, eliminating duplicated serialization logic and error handling, namely incorrect input types when serializing, and malformed data when deserializing. They also allow services to answer questions like "is this Macaroon well-formed for this schema?"

Let's look at Robert's example:

    expires: %Y-%m-%dT%H:%M:%S

This is a valid ISO 8601 date, but there's a problem: it doesn't include a time zone identifier. The ISO 8601 implementation I'm using in Ruby treats this as being in my local time zone:

    >> Time.iso8601("2015-12-23T13:17:26")
     => 2015-12-23 13:17:26 -0800

But perhaps what was meant was GMT, in which case it should have a "Z" at the end. Robert's format, as stated, does not allow us to express a GMT date/time, but one that is interpreted as a local time.

I would suggest standardizing on ISO 8601: https://github.com/cryptosphere/boulangerie/wiki/Types#datetime

With a standard for representing DateTimes, all predicate verifiers can operate on their language's native DateTime type, and all the DateTime parsing can be centralized.

Perhaps the most important thing to me is Lists. I think caveats often express overlapping set memberships. Having a standard syntax for representing lists/sets seems important for this reason. And there are all sorts of things to bikeshed: do we use commas, or a lispier " "? Are multiple spaces allowed? If we're using commas, is a space after a comma allowed?

For a predicate I would expect something like a BNF *1) describing possible contents.
This could also be visualized in fancy rail-road-diagrams, like e.g. on json.org.

I described the types using unambiguous regular expressions (or references to other standards for ISO 8601 and URI Generic Syntax). Regular expressions can be expanded into fancy json.org-like state machines if you so desire.

The only place an (A)BNF grammar would apply is to the List syntax. I am explicitly eschewing nested lists, making the grammar completely regular as it contains no pushdowns. As the types are all self-contained, it can be thought of as a set of mini-languages, where each type is its own language. I would agree it could be more formally described.

--
Tony Arcieri

Tony Arcieri

unread,
Dec 23, 2015, 4:30:41 PM12/23/15
to maca...@googlegroups.com, Jørn Wildt
On Wed, Dec 23, 2015 at 1:28 PM, Robert Escriva <rob...@rescrv.net> wrote:
I think it best to declare all expires to be utc. This puts the burden on the user to convert to utc, but greatly reduces the complexity of macaroons. Further it guarantees that there is no error in misinterpreting timezones. The ISO standard you listed is merely a constant offset from utc anyway.

That's only if you include a "Z" at the end. Otherwise, at least in one implementation I tested, it's interpreted as local time.

I selected ISO 8601 for my DateTimes already, but I would be happy to mandate times always be UTC, which would be your format + "Z".
 
--
Tony Arcieri

Robert Escriva

unread,
Dec 23, 2015, 4:32:45 PM12/23/15
to maca...@googlegroups.com, Tony Arcieri, Jørn Wildt
I'm amenable to the z so long as with and without the z are interpreted as utc.

I think you've inspired me to write up my thoughts on macaroon standardization and common patterns.

Jørn Wildt

unread,
Dec 23, 2015, 4:37:29 PM12/23/15
to maca...@googlegroups.com
I'm amenable to the z so long as with and without the z are interpreted as utc.

Why not stick to a standard and follow it: Z means GMT and no Z means local time. In that way implementers don't have to work against the frameworks they are using and manually convert no Z to mean GMT.

/Jørn

--
You received this message because you are subscribed to the Google Groups "Macaroons" group.
To unsubscribe from this group and stop receiving emails from it, send an email to macaroons+...@googlegroups.com.
To post to this group, send email to maca...@googlegroups.com.

Tony Arcieri

unread,
Dec 23, 2015, 5:12:44 PM12/23/15
to maca...@googlegroups.com
On Wed, Dec 23, 2015 at 12:13 PM, Robert Escriva <rob...@rescrv.net> wrote:
I'd recommend that we simply adopt the convention that first party
caveats must be unique to the project in the first N letters (similar to
how C projects work).  It adds a bit of overhead, but is worth allowing
multiple frameworks to develop on top.

I'd like to go back to this point. I think this is a good idea. I guess the question is how long is N?

There was some discussion of using URNs for CIDs, and I think I like that. However I totally recognize that some people would much rather not use URNs, and I respect that. To disambiguate from URNs and other use cases, it'd be nice if the first 4 bytes were required to be unique, in which case "urn:" would be unambiguous for these use cases.

--
Tony Arcieri

Robert Escriva

unread,
Dec 23, 2015, 5:34:56 PM12/23/15
to maca...@googlegroups.com, Jørn Wildt
Then I'd recommend Z being the only acceptable option. The beauty of macaroons is that they are simple and it's the proof tree constructed by the macaroons that encodes the authorization. The more logic that gets pushed into caveat checkers, the more complex an implementation must be, and the more likely it is to get things wrong. In a general application, flexibility is your friend. In the authorization layer, simplicity means that the coffee is easy to audit, easy to reimplement correctly, and easy to describe to others.

What's beautiful about macaroons is there is zero need to put the "is this utc or Europe/Amsterdam pre 1937" logic into the verifier. We can put a simple, auditable "expires" caveat into the verifier and leave all the complexity in the caveat generator. There's zero loss of functionality, as you can do all timezone handling at the time you create the caveat; you can even do it from a reusable framework. And your target service is none-the-wiser.

Let's keep this simple as complexity breeds complexity.

Tony Arcieri

unread,
Dec 23, 2015, 5:42:32 PM12/23/15
to maca...@googlegroups.com, Jørn Wildt
On Wed, Dec 23, 2015 at 2:34 PM, Robert Escriva <rob...@rescrv.net> wrote:
Then I'd recommend Z being the only acceptable option.

+1 

--
Tony Arcieri
Reply all
Reply to author
Forward
0 new messages