Merge branch 'master' into version-0.14

This commit is contained in:
Jens Langhammer 2020-12-31 11:55:59 +01:00
commit 101b973cfe
23 changed files with 164 additions and 72 deletions

80
Pipfile.lock generated
View file

@ -74,18 +74,18 @@
},
"boto3": {
"hashes": [
"sha256:ba8de10d3ede338d51ae47e428b97dcc1d1b507741aa98697e63e879a147f4aa",
"sha256:e3f10ed6d9ca98415fdec15c85e50a89ec38d6229bce3fafd5e7965b16c4ebc5"
"sha256:197926eaf0065c2c503914a15edc75f4ac259c1e5ae6d17eabd1ba5d8ebd1554",
"sha256:d6991e6fd7d0f63bf94282687700a91f5299b807e544cb3367e9b2faeeaf8c62"
],
"index": "pypi",
"version": "==1.16.44"
"version": "==1.16.46"
},
"botocore": {
"hashes": [
"sha256:4ff05bc089ba78a5996f06dcfddf8ca51583e30ce779ed95e9952e90c1907420",
"sha256:7725e08c95ae96c4dbd955cb4ae44a0c06d3e41f76a7feb0a941c27a44c63113"
"sha256:85ca6915ad5471e7f6cd1b00610b74601d2970cbf8e9b1bf255697154cf621a3",
"sha256:f7d365c689070368a5a0857aa35a81d7c950556189f23065f42798f810a59cae"
],
"version": "==1.19.44"
"version": "==1.19.46"
},
"cachetools": {
"hashes": [
@ -1083,11 +1083,11 @@
"standard"
],
"hashes": [
"sha256:6707fa7f4dbd86fd6982a2d4ecdaad2704e4514d23a1e4278104311288b04691",
"sha256:d19ca083bebd212843e01f689900e5c637a292c63bb336c7f0735a99300a5f38"
"sha256:1079c50a06f6338095b4f203e7861dbff318dde5f22f3a324fc6e94c7654164c",
"sha256:ef1e0bb5f7941c6fe324e06443ddac0331e1632a776175f87891c7bd02694355"
],
"index": "pypi",
"version": "==0.13.2"
"version": "==0.13.3"
},
"uvloop": {
"hashes": [
@ -1741,38 +1741,38 @@
},
"typed-ast": {
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
"sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
"sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
"sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
"sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
"sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
"sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1",
"sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d",
"sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6",
"sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd",
"sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37",
"sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151",
"sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07",
"sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440",
"sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70",
"sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496",
"sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea",
"sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400",
"sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc",
"sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606",
"sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc",
"sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581",
"sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412",
"sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a",
"sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2",
"sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787",
"sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f",
"sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937",
"sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64",
"sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487",
"sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b",
"sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41",
"sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a",
"sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3",
"sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166",
"sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"
],
"version": "==1.4.1"
"version": "==1.4.2"
},
"typing-extensions": {
"hashes": [

View file

@ -6,9 +6,9 @@ As authentik is currently in a pre-stable, only the latest "stable" version is s
| Version | Supported |
| -------- | ------------------ |
| 0.11.x | :white_check_mark: |
| 0.12.x | :white_check_mark: |
| 0.13.x | :white_check_mark: |
| 0.14.x | :white_check_mark: |
## Reporting a Vulnerability

View file

@ -29,7 +29,7 @@ class ApplicationCreateView(
permission_required = "authentik_core.add_application"
template_name = "generic/create.html"
success_url = reverse_lazy("authentik_admin:applications")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully created Application")
@ -47,7 +47,7 @@ class ApplicationUpdateView(
permission_required = "authentik_core.change_application"
template_name = "generic/update.html"
success_url = reverse_lazy("authentik_admin:applications")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully updated Application")
@ -60,5 +60,5 @@ class ApplicationDeleteView(
permission_required = "authentik_core.delete_application"
template_name = "generic/delete.html"
success_url = reverse_lazy("authentik_admin:applications")
success_url = reverse_lazy("authentik_core:shell")
success_message = _("Successfully deleted Application")

View file

@ -11,6 +11,7 @@ from django.views.debug import SafeExceptionReporterFilter
from guardian.utils import get_anonymous_user
from authentik.core.models import User
from authentik.policies.types import PolicyRequest
# Special keys which are *not* cleaned, even when the default filter
# is matched
@ -74,6 +75,11 @@ def sanitize_dict(source: Dict[Any, Any]) -> Dict[Any, Any]:
final_dict = {}
for key, value in source.items():
if is_dataclass(value):
# Because asdict calls `copy.deepcopy(obj)` on everything thats not tuple/dict,
# and deepcopy doesn't work with HttpRequests (neither django nor rest_framework).
# Currently, the only dataclass that actually holds an http request is a PolicyRequest
if isinstance(value, PolicyRequest):
value.http_request = None
value = asdict(value)
if isinstance(value, dict):
final_dict[key] = sanitize_dict(value)

View file

@ -56,6 +56,7 @@ class PolicyEngine:
raise ValueError(f"{pbm} is not instance of PolicyBindingModel")
self.__pbm = pbm
self.request = PolicyRequest(user)
self.request.obj = pbm
if request:
self.request.http_request = request
self.__cached_policies = []

View file

@ -93,4 +93,8 @@ class PolicyProcess(Process):
span: Span
span.set_data("policy", self.binding.policy)
span.set_data("request", self.request)
self.connection.send(self.execute())
try:
self.connection.send(self.execute())
except Exception as exc: # pylint: disable=broad-except
LOGGER.warning(exc)
self.connection.send(PolicyResult(False, str(exc)))

View file

@ -36,17 +36,17 @@ class SAMLProviderForm(forms.ModelForm):
"name",
"authorization_flow",
"acs_url",
"audience",
"issuer",
"sp_binding",
"audience",
"signing_kp",
"verification_kp",
"property_mappings",
"assertion_valid_not_before",
"assertion_valid_not_on_or_after",
"session_valid_not_on_or_after",
"digest_algorithm",
"signature_algorithm",
"signing_kp",
"verification_kp",
"property_mappings",
]
widgets = {
"name": forms.TextInput(),
@ -94,6 +94,9 @@ class SAMLProviderImportForm(forms.Form):
"""Create a SAML Provider from SP Metadata."""
provider_name = forms.CharField()
authorization_flow = forms.ModelChoiceField(
queryset=Flow.objects.filter(designation=FlowDesignation.AUTHORIZATION)
)
metadata = forms.FileField(
validators=[FileExtensionValidator(allowed_extensions=["xml"])]
)

View file

@ -0,0 +1,22 @@
# Generated by Django 3.1.4 on 2020-12-30 21:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_saml", "0009_auto_20201112_2016"),
]
operations = [
migrations.AlterField(
model_name="samlprovider",
name="audience",
field=models.TextField(
blank=True,
default="",
help_text="Value of the audience restriction field of the asseration. When left empty, no audience restriction will be added.",
),
),
]

View file

@ -42,7 +42,13 @@ class SAMLProvider(Provider):
acs_url = models.URLField(verbose_name=_("ACS URL"))
audience = models.TextField(
default="",
help_text=_("Value of the audience restriction field of the asseration."),
blank=True,
help_text=_(
(
"Value of the audience restriction field of the asseration. When left empty, "
"no audience restriction will be added."
)
),
)
issuer = models.TextField(
help_text=_("Also known as EntityID"), default="authentik"

View file

@ -127,11 +127,14 @@ class AssertionProcessor:
conditions = Element(f"{{{NS_SAML_ASSERTION}}}Conditions")
conditions.attrib["NotBefore"] = self._valid_not_before
conditions.attrib["NotOnOrAfter"] = self._valid_not_on_or_after
audience_restriction = SubElement(
conditions, f"{{{NS_SAML_ASSERTION}}}AudienceRestriction"
)
audience = SubElement(audience_restriction, f"{{{NS_SAML_ASSERTION}}}Audience")
audience.text = self.provider.audience
if self.provider.audience != "":
audience_restriction = SubElement(
conditions, f"{{{NS_SAML_ASSERTION}}}AudienceRestriction"
)
audience = SubElement(
audience_restriction, f"{{{NS_SAML_ASSERTION}}}Audience"
)
audience.text = self.provider.audience
return conditions
def get_name_id(self) -> Element:

View file

@ -5,6 +5,7 @@ from typing import Optional
import xmlsec
from cryptography.hazmat.backends import default_backend
from cryptography.x509 import load_pem_x509_certificate
from defusedxml.lxml import fromstring
from lxml import etree # nosec
from structlog import get_logger
@ -23,6 +24,8 @@ LOGGER = get_logger()
def format_pem_certificate(unformatted_cert: str) -> str:
"""Format single, inline certificate into PEM Format"""
# Ensure that all linebreaks are gone
unformatted_cert = unformatted_cert.replace("\n", "")
chunks, chunk_size = len(unformatted_cert), 64
lines = [PEM_HEADER]
for i in range(0, chunks, chunk_size):
@ -52,10 +55,14 @@ class ServiceProviderMetadata:
provider.issuer = self.entity_id
provider.sp_binding = self.acs_binding
provider.acs_url = self.acs_location
if self.signing_keypair:
if self.signing_keypair and self.auth_n_request_signed:
self.signing_keypair.name = f"Provider {name} - SAML Signing Certificate"
self.signing_keypair.save()
provider.signing_kp = self.signing_keypair
provider.verification_kp = self.signing_keypair
if self.assertion_signed:
provider.signing_kp = CertificateKeyPair.objects.exclude(
key_data__iexact=""
).first()
return provider
@ -104,7 +111,7 @@ class ServiceProviderMetadataParser:
def parse(self, raw_xml: str) -> ServiceProviderMetadata:
"""Parse raw XML to ServiceProviderMetadata"""
root = etree.fromstring(raw_xml) # nosec
root = fromstring(raw_xml.encode())
entity_id = root.attrib["entityID"]
sp_sso_descriptors = root.findall(f"{{{NS_SAML_METADATA}}}SPSSODescriptor")

View file

@ -84,7 +84,9 @@ class TestServiceProviderMetadataParser(TestCase):
provider.issuer, "http://localhost:8080/apps/user_saml/saml/metadata"
)
self.assertEqual(provider.sp_binding, SAMLBindings.POST)
self.assertEqual(provider.signing_kp.certificate_data, CERT)
self.assertEqual(provider.verification_kp.certificate_data, CERT)
self.assertIsNotNone(provider.signing_kp)
self.assertEqual(provider.audience, "")
def test_with_signing_cert_invalid_signature(self):
"""Test Metadata with signing cert (invalid signature)"""

View file

@ -270,8 +270,14 @@ class MetadataImportView(LoginRequiredMixin, FormView):
form.cleaned_data["metadata"].read().decode()
)
provider = metadata.to_provider(form.cleaned_data["provider_name"])
provider.authorization_flow = form.cleaned_data["authorization_flow"]
provider.save()
messages.success(self.request, _("Successfully created Provider"))
except ValueError:
messages.error(self.request, _("Failed to import Metadata."))
except ValueError as exc:
LOGGER.warning(exc)
messages.error(
self.request,
_("Failed to import Metadata: %(message)s" % {"message": str(exc)}),
)
return super().form_invalid(form)
return super().form_valid(form)

View file

@ -8004,9 +8004,9 @@ definitions:
minLength: 1
audience:
title: Audience
description: Value of the audience restriction field of the asseration.
description: Value of the audience restriction field of the asseration. When
left empty, no audience restriction will be added.
type: string
minLength: 1
issuer:
title: Issuer
description: Also known as EntityID

6
web/package-lock.json generated
View file

@ -968,9 +968,9 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"construct-style-sheets-polyfill": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-2.4.3.tgz",
"integrity": "sha512-ECo96zFPsdghrMJmJ0vomcHsqLOIYpudobcNCIPeMubyFzBcLCfljuY0oFA3DD7btiFqB0sZ+0szbsiE8I24VA=="
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-2.4.6.tgz",
"integrity": "sha512-lU0to7dFDjKslMF+M5NUa4s0RQMBRVyZMXvD/vp7vmjdEPgziTkHSfZHQxfoIvVWajWRJUVJMLfrMwcx8fTh4A=="
},
"copy-descriptor": {
"version": "0.1.1",

View file

@ -15,7 +15,7 @@
"@types/codemirror": "0.0.103",
"chart.js": "^2.9.4",
"codemirror": "^5.59.0",
"construct-style-sheets-polyfill": "^2.4.3",
"construct-style-sheets-polyfill": "^2.4.6",
"flowchart.js": "^1.15.0",
"lit-element": "^2.4.0",
"lit-html": "^1.3.0",

View file

@ -8,7 +8,7 @@ export interface EventUser {
}
export interface EventContext {
[key: string]: EventContext | string | number;
[key: string]: EventContext | string | number | string[];
}
export class Event {

View file

@ -137,6 +137,9 @@ select[multiple] {
--pf-c-table--cell--Color: var(--ak-dark-foreground);
}
.pf-c-table__text {
color: var(--ak-dark-foreground);
}
.pf-c-table__sort:not(.pf-m-selected) .pf-c-table__button .pf-c-table__text {
color: var(--ak-dark-foreground) !important;
}
.pf-c-table__sort-indicator i {

View file

@ -15,10 +15,10 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
}),
new SidebarItem("Administration").children(
new SidebarItem("Applications", "/applications").activeWhen(
`^/applications/(?<slug>${SLUG_REGEX})/$`
`^/applications/(?<slug>${SLUG_REGEX})$`
),
new SidebarItem("Sources", "/administration/sources/").activeWhen(
`^/sources/(?<slug>${SLUG_REGEX})/$`,
`^/sources/(?<slug>${SLUG_REGEX})$`,
),
new SidebarItem("Providers", "/administration/providers/"),
new SidebarItem("Outposts", "/administration/outposts/"),

View file

@ -8,7 +8,7 @@ import "../elements/sidebar/SidebarHamburger";
export abstract class Interface extends LitElement {
@property({type: Boolean})
sidebarOpen?: boolean;
sidebarOpen = true;
abstract get sidebar(): SidebarItem[];

View file

@ -51,7 +51,7 @@ export class ApplicationListPage extends TablePage<Application> {
${item.meta_icon ?
html`<img class="app-icon pf-c-avatar" src="${item.meta_icon}" alt="${gettext("Application Icon")}">` :
html`<i class="pf-icon pf-icon-arrow"></i>`}`,
html`<a href="#/applications/${item.slug}/">
html`<a href="#/applications/${item.slug}">
<div>
${item.name}
</div>

View file

@ -94,6 +94,29 @@ export class EventInfo extends LitElement {
<code>${this.event.context.expression}</code>
</div>
</div>`;
case "policy_execution":
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${gettext("Request")}</h3>
<ul class="pf-c-list">
<li>${gettext("Object")}: ${(this.event.context.request as EventContext).obj as string}</li>
<li><span>${gettext("Context")}: <code>${JSON.stringify((this.event.context.request as EventContext).context)}</code></span></li>
</ul>
</div>
<div class="pf-l-flex__item">
<h3>${gettext("Result")}</h3>
<ul class="pf-c-list">
<li>${gettext("Passing")}: ${(this.event.context.result as EventContext).passing}</li>
<li>${gettext("Messages")}:
<ul class="pf-c-list">
${((this.event.context.result as EventContext).messages as string[]).map(msg => {
return html`<li>${msg}</li>`;
})}
</ul>
</li>
</ul>
</div>
</div>`;
case "configuration_error":
return html`<h3>${this.event.context.message}</h3>`;
case "update_available":

View file

@ -30,6 +30,12 @@ export class SiteShell extends LitElement {
::slotted(*) {
height: 100%;
}
.pf-l-bullseye {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
`,
BackdropStyle,
BullseyeStyle,