Using flat-manager for private app repo

Dan Nicholson nicholson at endlessm.com
Fri May 3 12:15:38 UTC 2019


On Fri, May 3, 2019 at 3:44 AM Alexander Larsson <alexl at redhat.com> wrote:
>
> On Thu, May 2, 2019 at 6:13 PM Dan Nicholson <nicholson at endlessm.com> wrote:
> >
> > So, probably there is a way to make the CDN edge server handle
> > authorization, although it would be specific to the CDN provider. That
> > said, I think it should be possible to deploy a private app store
> > without also requiring on a CDN. In other words, I think it should be
> > possible to handle the authorization at both the origin and edge
> > server.
>
> Yes, I think most CDNs support *something* like this, because it is
> how everyone seems to implement things like private or for-pay
> downloads. So, what we need to do is to look at the most common CDNs
> and make sure that the methods we support allows implementations on
> all (or most) of these. Of particular importance are fastly (for
> flathub) and whatever CDNs endless ends up using.

Yeah, makes sense.

> > One thing that could be useful is an API endpoint that takes a ref and
> > returns a list of commit and delta superblock URL paths. Then the
> > authorization server could generate the proper signed URLs in the
> > format the CDN needed after determining that the user was allowed to
> > access a specific ref. I don't know, I haven't quite been able to
> > figure out how this would go.
>
> I'm not sure what this would be used for. This is like moving to the
> client the set of urls you're required to supply a token for. But that
> seems backwards, it is the CDN (or proxy or whatever) that need to
> know if a url needs a token, we can't trust the client in this. How
> did you imagine this API being used?

Because I believe the CDN signed URLs need to happen in the
authorization server or the CDN itself, and neither would have this
application specific knowledge.

> We do however need to know this. But I don't think you ever need this
> full list? Instead what the client does is look at the summary file,
> figures out which commit and delta uris to download, and then just
> does it, passing in the token the auth server gave it (for this ref)
> to every such request. Then the CDN/flat-manager needs to know if this
> particular ref requires a token, and if so which token.
>
> This can happen in two ways:
> 1 ) The check happens directly in flat-manager, where it just returns
> a 403 error if the token is missing
> 2) The check happens in the CDN, but it has no idea initially, so it
> proxies the request to flat-manager, and flat-manager knows which/if
> any token is needed, and returns the result + a header telling the cdn
> which token it needs to apply.
>
> This is how we support both direct and CDNed access control. Maybe
> flat-manager has a known list of CDN ip address sources where it does
> 2, and otherwise it does 1. Or maybe the CDN sets some magic secret
> when proxying.

I don't see how 2 could work generally. If the CDN has an
authentication requirement (say, a signed URL), then the CDN will just
respond with a 403 if the incoming request isn't appropriately signed.
It won't pass the request through to the origin since that would be
the opposite of requiring authentication at the edge. I believe the
only way this would work would be for the authorization server to know
about the CDN authentication scheme and send back tokens that both the
CDN and flat-manager understand.

> Of course, this all means that flat-manager needs to know for each
> commit/delta url request what token is required. Each commit object
> has the ref bindings in them, and each delta superblock file has a
> copy of the commit object, so it would be easy for flat-manager to
> extract these if the url format matches, and either verify the header
> or set the ref in a header in the response. Actually, it would
> probably be fine to just always set it in the response to a commit or
> delta superblock request.
>
> The question then becomes, given the ref, how do we know if the app
> has access to it. The simplest way I can think of is:
>  1) Make the token contain a list of ref globs, like "*/org.the.app*/*/stable"
> 2) Split free and for-pay refs into different repos and apply token
> requirements to all downloads in the for-pay repo.
>
> The alternative to 2 is to mark up each ref somehow, but it seems
> easier both from a server side and client side (you need to figure out
> when you need to request a token) to have this be a global option per
> repo.

Yep, that's pretty much what I had in mind. I think there's a way to
make the existing prefixes work, but the globbing (or a regex) would
be more flexible. I also thought there could be a way to maintain free
refs in the same repo if flat-manager knew which refs were free. Then
it could skip the token check for those refs. But I don't know exactly
how and where you'd define that, so I decided it would be simpler to
start by requiring that the repo is either public or private and all
commit access in the latter requires a token that specifies the
allowed refs.

> This doesn't seem *that* hard, although its going to need some work:
> 1) Support in ostree/flatpak for a needs-token per-remote config where
> we go to an auth server and get a token for all refs required in a
> pull. Actually, this might not actually need to touch the ostree code,
> it might be possible to user the http-headers option of
> ostree_repo_pull_with_options().

Yeah, I think just putting the Authorization in the headers in the
pull options is the way to go. I don't think ostree needs to know at
all (unless you wanted to extend this to general ostree usage) The
trick is telling the clients (flatpak, gnome-software, etc) where they
should go check for credentials. But I think it would be easy enough
to put a URL in the realm in the WWW-Authenticate header returned with
a 401 (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate).
But a custom X-Flatpak-Auth-URL: https://auth.example.com or similar
would also work.

> 2) Support in flat-manager to extract the ref bindings for commit and
> delta superblock files

Yeah. I was already looking at this a bit. What I've done in the past
(https://github.com/ostreedev/ostree-releng-scripts/pull/12) is to
just walk each ref and keep a map of commits to refs (or vice versa).
I hadn't thought about using the ref bindings, but that's even faster.
A 3rd option I thought about was keeping a table in the database with
this info.

Do you have any objection to pulling in the libostree crate in
flat-manager. I'd much rather use the ostree API for this kind of
stuff than open coding GVariant parsing (bravo to you for that!).

> 3) Support in flat-manager to optionally verify ref binding vs the
> token (this should probably use a separate secret from the one used
> for auth:ing the build APIs, and probably a different, simpler token
> format).

I don't think you really need a separate secret - just because you
used it to generate 2 different types of tokens, the risk of losing
them is the same. But I don't think coming up with a token format
specifically for this use case is best.

> 4) Research into various CDN configurations

As mentioned above, I think this would be tricky, but I'm sure there's
a way. In the absence of configuring authentication at the CDN, then I
think flat-manager needs to set the Cache-Control header to no-store
on commit objects and delta superblocks so that if there is a CDN in
front of it that it doesn't start serving a cached version to anyone
that comes along.

> Most of this looks relatively simple actually. The most problematic
> part is probably going to be the API to the authentication server. In
> particular how you authenticate to that. The details of this
> authentication is likely to be different for every repo provider (user
> + password, email + password, api token, etc) and the secret will have
> to be stored somewhere in the flatpak configuration, or provided in
> some secure way. This must both be flexible and secure, which is a
> hard combination.

Totally agree that the server side is actually fairly simple (besides
the CDN integration), but the client side will be more challenging.
I've thought about it a few times, but I haven't come up with much.
That said, this really isn't any different than using a 3rd party
online identity provider. Maybe we should look at how GOA does it. At
least for how to talk to the auth server and how to store the secrets
locally.

--
Dan


More information about the Flatpak mailing list