transaction: Request required tokens from configured authenticator

When we need a bearer token, look up the configured authenticator for
the remote and ask it for tokens. Also updates the test-auth test
with to use the new test authenticator instead of the previous
env var hack.
This commit is contained in:
Alexander Larsson
2019-10-17 17:00:32 +02:00
committed by Alexander Larsson
parent 8d02d86463
commit ae13e31510
2 changed files with 109 additions and 21 deletions

View File

@@ -28,6 +28,7 @@
#include "flatpak-installation-private.h"
#include "flatpak-utils-private.h"
#include "flatpak-error.h"
#include "flatpak-auth-private.h"
/**
* SECTION:flatpak-transaction
@@ -2599,6 +2600,24 @@ resolve_all_ops (FlatpakTransaction *self,
return TRUE;
}
typedef struct {
FlatpakTransaction *transaction;
gboolean done;
guint response;
GVariant *results;
} RequestTokensData;
static void
request_tokens_response (FlatpakAuthenticatorRequest *object,
guint response,
GVariant *results,
RequestTokensData *data)
{
data->response = response;
data->results = g_variant_ref (results);
data->done = TRUE;
}
static gboolean
request_tokens_for_remote (FlatpakTransaction *self,
@@ -2607,34 +2626,90 @@ request_tokens_for_remote (FlatpakTransaction *self,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GString) refs_as_str = g_string_new ("");
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
g_autofree char *refs_as_str = NULL;
GList *l;
const char *token;
g_autoptr(GPtrArray) refs = g_ptr_array_new ();
g_autoptr(AutoFlatpakAuthenticatorRequest) request = NULL;
g_autoptr(AutoFlatpakAuthenticator) authenticator = NULL;
g_autoptr(GMainContextPopDefault) context = NULL;
RequestTokensData data = { self };
g_autoptr(GVariant) tokens = NULL;
g_autoptr(GVariant) results = NULL;
for (l = ops; l != NULL; l = l->next)
{
FlatpakTransactionOperation *op = l->data;
g_ptr_array_add (refs, op->ref);
}
g_ptr_array_add (refs, NULL);
if (l != ops)
g_string_append (refs_as_str, ", ");
g_string_append (refs_as_str, op->ref);
refs_as_str = g_strjoinv (", ", (char **)refs->pdata);
g_debug ("Requesting tokens for remote %s, refs: %s", remote, refs_as_str);
context = flatpak_main_context_new_default ();
authenticator = flatpak_auth_new_for_remote (priv->dir, remote, cancellable, error);
if (authenticator == NULL)
return FALSE;
request = flatpak_auth_create_request (authenticator, cancellable, error);
if (request == NULL)
return FALSE;
g_signal_connect (request, "response", (GCallback)request_tokens_response, &data);
if (!flatpak_auth_request_ref_tokens (authenticator, request, (const char **)refs->pdata, cancellable, error))
return FALSE;
while (!data.done)
g_main_context_iteration (context, TRUE);
results = data.results; /* Make sure its freed as needed */
{
g_autofree char *results_str = g_variant_print (results, FALSE);
g_debug ("Response from request_tokens: %d - %s\n", data.response, results_str);
}
if (data.response == FLATPAK_AUTH_RESPONSE_CANCELLED)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
"User cancelled authentication request");
return FALSE;
}
g_debug ("Requesting tokens for remote %s, refs: %s", remote, refs_as_str->str);
if (data.response != FLATPAK_AUTH_RESPONSE_OK)
return flatpak_fail (error, "Failed to get tokens for ref");
/* FIXME: This is just some temporary testing code and will be
replaces with a callout later. */
token = g_getenv ("FLATPAK_TEST_TOKEN");
if (token == NULL)
token = "default-token";
g_debug ("Got token %s", token);
tokens = g_variant_lookup_value (results, "tokens", G_VARIANT_TYPE ("a{sas}"));
if (tokens == NULL)
return flatpak_fail (error, "Authenticator didn't send requested tokens");
for (l = ops; l != NULL; l = l->next)
{
FlatpakTransactionOperation *op = l->data;
GVariantIter iter;
const char *token = NULL;
const char *token_for_refs;
g_autofree const char **refs;
op->resolved_token = g_strdup (token);
g_variant_iter_init (&iter, tokens);
while (g_variant_iter_next (&iter, "{&s^a&s}", &token_for_refs, &refs))
{
if (g_strv_contains (refs, op->ref))
{
token = token_for_refs;
break;
}
}
if (token == NULL)
return flatpak_fail (error, "Authenticator didn't send tokens for ref");
/* Allow sending empty tokens to mean no token needed */
op->resolved_token = *token == 0 ? NULL : g_strdup (token);
op->requested_token = TRUE;
}

View File

@@ -47,7 +47,6 @@ assert_failed_with_401 () {
fi
}
# Mark as need token, even though the app doesn't have token-type set
# We should not be able to install this because we will not present
# the token unnecessarily
@@ -62,26 +61,38 @@ assert_failed_with_401
EXPORT_ARGS="--token-type=2" make_updated_app
mark_need_token app/org.test.Hello/$ARCH/master the-secret
# Install with no authenticator
if ${FLATPAK} ${U} install -y test-repo org.test.Hello master 2> install-error-log; then
assert_not_reached "Should not be able to install without authenticator"
fi
assert_file_has_content install-error-log "No authenticator configured for remote"
${FLATPAK} ${U} remote-modify test-repo --authenticator-name org.flatpak.Authenticator.test
# Install with wrong token
if FLATPAK_TEST_TOKEN=not-the-secret ${FLATPAK} ${U} install -y test-repo org.test.Hello master 2> install-error-log; then
echo -n not-the-secret > ${XDG_RUNTIME_DIR}/required-token
if ${FLATPAK} ${U} install -y test-repo org.test.Hello master 2> install-error-log; then
assert_not_reached "Should not be able to install with wrong secret"
fi
assert_failed_with_401
# Install with right token
FLATPAK_TEST_TOKEN=the-secret ${FLATPAK} ${U} install -y test-repo org.test.Hello master
echo -n the-secret > ${XDG_RUNTIME_DIR}/required-token
${FLATPAK} ${U} install -y test-repo org.test.Hello master
EXPORT_ARGS="--token-type=2" make_updated_app test "" master UPDATE2
mark_need_token app/org.test.Hello/$ARCH/master the-secret
# Update with wrong token
if FLATPAK_TEST_TOKEN=not-the-secret ${FLATPAK} ${U} update -y org.test.Hello 2> install-error-log; then
echo -n not-the-secret > ${XDG_RUNTIME_DIR}/required-token
if ${FLATPAK} ${U} update -y org.test.Hello 2> install-error-log; then
assert_not_reached "Should not be able to install with wrong secret"
fi
assert_failed_with_401
# Update with right token
FLATPAK_TEST_TOKEN=the-secret ${FLATPAK} ${U} update -y org.test.Hello
echo -n the-secret > ${XDG_RUNTIME_DIR}/required-token
${FLATPAK} ${U} update -y org.test.Hello
echo "ok installed build-exported token-type app"
@@ -95,12 +106,14 @@ $FLATPAK build-commit-from ${FL_GPGARGS} --token-type=2 --disable-fsync --src-r
mark_need_token app/org.test.Hello/$ARCH/copy the-secret
# Install with wrong token
if FLATPAK_TEST_TOKEN=not-the-secret ${FLATPAK} ${U} install -y test-repo org.test.Hello//copy 2> install-error-log; then
echo -n not-the-secret > ${XDG_RUNTIME_DIR}/required-token
if ${FLATPAK} ${U} install -y test-repo org.test.Hello//copy 2> install-error-log; then
assert_not_reached "Should not be able to install with wrong secret"
fi
assert_failed_with_401
# Install with right token
FLATPAK_TEST_TOKEN=the-secret ${FLATPAK} ${U} install -y test-repo org.test.Hello//copy
echo -n the-secret > ${XDG_RUNTIME_DIR}/required-token
${FLATPAK} ${U} install -y test-repo org.test.Hello//copy
echo "ok installed build-commit-from token-type app"