authentik icon indicating copy to clipboard operation
authentik copied to clipboard

`ak export_blueprint` does not work

Open achernya opened this issue 3 years ago • 5 comments

Describe the bug It seems that there's a series of bugs that prevent ak export_blueprint from working on an up-to-date 2022.8.2 Authentik instance.

To Reproduce Steps to reproduce the behavior:

  1. Inside the docker container, run ak export_blueprint

Expected behavior An export of the blueprints in the instance is produced.

Logs

I have no name!@e06979d04acf:/$ ak export_blueprint
{"event": "Loaded config", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1661639588.551532, "file": "/authentik/lib/default.yml"}
{"event": "Loaded environment variables", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1661639588.5517583, "count": 6}
{"event": "Booting authentik", "level": "info", "logger": "authentik.root.settings", "timestamp": 1661639588.913549, "version": "2022.8.2"}
{"event": "Failed to load GeoIP database", "exc": "FileNotFoundError(2, 'No such file or directory')", "level": "warning", "logger": "authentik.events.geo", "pid": 4033, "timestamp": "2022-08-27T22:33:09.280181"}
{"event": "Task published", "level": "info", "logger": "authentik.root.celery", "pid": 4033, "task_id": "8dad8709-53f9-4d5d-8c34-10e4330a2463", "task_name": "authentik.blueprints.v1.tasks.blueprints_discover", "timestamp": "2022-08-27T22:33:09.656647"}
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/manage.py", line 38, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 448, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 96, in wrapped
    res = handle_func(*args, **kwargs)
  File "/authentik/blueprints/management/commands/export_blueprint.py", line 17, in handle
    self.stdout.write(exporter.export_to_string())
  File "/authentik/blueprints/v1/exporter.py", line 63, in export_to_string
    blueprint = self.export()
  File "/authentik/blueprints/v1/exporter.py", line 58, in export
    blueprint.entries = list(self.get_entries())
  File "/authentik/blueprints/v1/exporter.py", line 43, in get_entries
    yield BlueprintEntry.from_model(obj)
  File "/authentik/blueprints/v1/common.py", line 63, in from_model
    all_attrs = get_attrs(model)
  File "/authentik/blueprints/v1/common.py", line 22, in get_attrs
    data = dict(serializer.data)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 555, in data
    ret = super().data
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/fields.py", line 1886, in to_representation
    return method(value)
  File "/authentik/core/api/applications.py", line 53, in get_launch_url
    user = self.context["request"].user
KeyError: 'request'

If I monkey-patch around this error,

I have no name!@e06979d04acf:/$ python -m manage shell
{"event": "Loaded config", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1661639750.0241816, "file": "/authentik/l
ib/default.yml"}
{"event": "Loaded environment variables", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1661639750.0244184, "count
": 6}
{"event": "Booting authentik", "level": "info", "logger": "authentik.root.settings", "timestamp": 1661639750.3875265, "version": "202
2.8.2"}
{"event": "Failed to load GeoIP database", "exc": "FileNotFoundError(2, 'No such file or directory')", "level": "warning", "logger":
"authentik.events.geo", "pid": 4090, "timestamp": "2022-08-27T22:35:50.737404"}
{"event": "Task published", "level": "info", "logger": "authentik.root.celery", "pid": 4090, "task_id": "156db57e-730e-44c1-b10a-b6a1
19d37d02", "task_name": "authentik.blueprints.v1.tasks.blueprints_discover", "timestamp": "2022-08-27T22:35:51.097681"}
### authentik shell (2022.8.2)
### Node e06979d04acf | Arch x86_64 | Python 3.10.6
>>> from authentik.blueprints.v1.exporter import Exporter
>>> import authentik.core.api
>>> authentik.core.api.applications.ApplicationSerializer.get_launch_url = lambda x,y: None

I end up with a new stack trace:

>>> exporter = Exporter()
>>> exporter.export_to_string()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/authentik/blueprints/v1/exporter.py", line 64, in export_to_string
    return dump(blueprint, Dumper=BlueprintDumper)
  File "/usr/local/lib/python3.10/site-packages/yaml/__init__.py", line 253, in dump
    return dump_all([data], stream, Dumper=Dumper, **kwds)
  File "/usr/local/lib/python3.10/site-packages/yaml/__init__.py", line 241, in dump_all
    dumper.represent(data)
  File "/authentik/blueprints/v1/common.py", line 240, in represent
    return super().represent(data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 27, in represent
    node = self.represent_data(data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 48, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 207, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 118, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 48, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 199, in represent_list
    return self.represent_sequence('tag:yaml.org,2002:seq', data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 92, in represent_sequence
    node_item = self.represent_data(item)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 48, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 207, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 118, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 48, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 207, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 118, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 48, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/authentik/blueprints/v1/common.py", line 228, in <lambda>
    self.add_representer(OrderedDict, lambda self, data: self.represent_dict(dict(data)))
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 207, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 118, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 58, in represent_data
    node = self.yaml_representers[None](self, data)
  File "/usr/local/lib/python3.10/site-packages/yaml/representer.py", line 231, in represent_undefined
    raise RepresenterError("cannot represent an object", data)
yaml.representer.RepresenterError: ('cannot represent an object', 'OAuth2/OpenID Provider')

This seems to be because

>>> import pdb
>>> pdb.pm()
> /usr/local/lib/python3.10/site-packages/yaml/representer.py(231)represent_undefined()
-> raise RepresenterError("cannot represent an object", data)
(Pdb) pp data
'OAuth2/OpenID Provider'
(Pdb) type(data)
<class 'django.utils.functional.lazy.<locals>.__proxy__'>

the string "OAuth2/OpenID Provider" is actually an object from Django with a string-like repr, and PyYAML doesn't have a registered representer. At this point I gave up trying to monkey-patch further.

Version and Deployment (please complete the following information):

  • authentik version: 2022.8.2
  • Deployment: docker-compose

Additional context Add any other context about the problem here.

achernya avatar Aug 27 '22 22:08 achernya

The initial issue is fixed with the commit above, I was not able to reproduce the second issue yet

BeryJu avatar Aug 28 '22 14:08 BeryJu

Thanks! For the 2nd stack trace I have a fairly simple local instance with Grafana set up as an Application with a dedicated Provider, following the Authentik documentation. I also have an LDAP outpost and the embedded outpost configured.

achernya avatar Aug 28 '22 14:08 achernya

I created an Application with an OAuth2 provider attached with all default settings and didnt get an error

the 2nd stack trace is caused by the OAuth2 Provider using lazy-translated strings for the model's verbose_name, and the verbose_name is returned via the API, however the blueprint export should filter out all instances of verbose_name fields

BeryJu avatar Aug 28 '22 14:08 BeryJu

I played around with the stacktrace with pdb a bit more. It was definitely trying to export the verbose_name. It seems to be coming from the OpenID provider:

yaml.representer.RepresenterError: ('cannot represent an object', 'OAuth2/OpenID Provider')
>>> import pdb
>>> pdb.pm()
> /usr/local/lib/python3.10/site-packages/yaml/representer.py(231)represent_undefined()
-> raise RepresenterError("cannot represent an object", data)
(Pdb) up
> /usr/local/lib/python3.10/site-packages/yaml/representer.py(58)represent_data()
-> node = self.yaml_representers[None](self, data)
(Pdb)
> /usr/local/lib/python3.10/site-packages/yaml/representer.py(118)represent_mapping()
-> node_value = self.represent_data(item_value)
(Pdb) p item_value
'OAuth2/OpenID Provider'
(Pdb) up
> /usr/local/lib/python3.10/site-packages/yaml/representer.py(207)represent_dict()
-> return self.represent_mapping('tag:yaml.org,2002:map', data)
(Pdb) pp data
{'access_code_validity': 'minutes=1',
 'assigned_application_name': 'Grafana',
 'assigned_application_slug': 'grafana',
 'authorization_flow': UUID('95571512-ce9d-4585-bf0e-524b83f3ad61'),
 'client_id': 'REDACTED',
 'client_secret': 'REDACTED',
 'client_type': 'confidential',
 'component': 'ak-provider-oauth2-form',
 'include_claims_in_id_token': True,
 'issuer_mode': 'per_provider',
 'jwks_sources': [],
 'meta_model_name': 'authentik_providers_oauth2.oauth2provider',
 'name': 'Grafana OpenID',
 'pk': 1,
 'property_mappings': [UUID('72aaf93c-d397-4646-ac31-29eae0da5fe2'),
                       UUID('d7bd9c21-4fc2-4ee3-b2c9-faae050c36a2'),
                       UUID('f741b0f6-0cf5-4a52-874b-49d4d8b74aa2')],
 'redirect_uris': 'https://REDACTED/login/generic_oauth',
 'signing_key': UUID('5d396d3f-b2eb-4b33-84fd-fdcc3ad143f3'),
 'sub_mode': 'hashed_user_id',
 'token_validity': 'days=30',
 'verbose_name': 'OAuth2/OpenID Provider',
 'verbose_name_plural': 'OAuth2/OpenID Providers'}

achernya avatar Aug 28 '22 21:08 achernya

So, any solution ?

skapin avatar Sep 07 '22 16:09 skapin