diff --git a/authentik/blueprints/models.py b/authentik/blueprints/models.py index d53fc12e6..121ae8f1c 100644 --- a/authentik/blueprints/models.py +++ b/authentik/blueprints/models.py @@ -92,7 +92,7 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): if ":" in url.path: path, _, ref = path.partition(":") client = NewClient( - f"{url.scheme}://{url.hostname}", + f"https://{url.hostname}", WithUserAgent(authentik_user_agent()), WithUsernamePassword(url.username, url.password), WithDefaultName(path), @@ -135,12 +135,11 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): def retrieve(self) -> str: """Retrieve blueprint contents""" + if self.path.startswith("oci://"): + return self.retrieve_oci() full_path = Path(CONFIG.y("blueprints_dir")).joinpath(Path(self.path)) - if full_path.exists(): - LOGGER.debug("Blueprint path exists locally", instance=self) - with full_path.open("r", encoding="utf-8") as _file: - return _file.read() - return self.retrieve_oci() + with full_path.open("r", encoding="utf-8") as _file: + return _file.read() @property def serializer(self) -> Serializer: diff --git a/web/src/admin/blueprints/BlueprintForm.ts b/web/src/admin/blueprints/BlueprintForm.ts index d31fca904..3c9520cdb 100644 --- a/web/src/admin/blueprints/BlueprintForm.ts +++ b/web/src/admin/blueprints/BlueprintForm.ts @@ -1,4 +1,5 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { docLink } from "@goauthentik/common/global"; import { first } from "@goauthentik/common/utils"; import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/forms/FormGroup"; @@ -8,19 +9,37 @@ import YAML from "yaml"; import { t } from "@lingui/macro"; -import { TemplateResult, html } from "lit"; -import { customElement } from "lit/decorators.js"; +import { CSSResult, TemplateResult, css, html } from "lit"; +import { customElement, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css"; + import { BlueprintInstance, ManagedApi } from "@goauthentik/api"; +enum blueprintSource { + local, + oci, +} + @customElement("ak-blueprint-form") export class BlueprintForm extends ModelForm { + @state() + source: blueprintSource = blueprintSource.local; + loadInstance(pk: string): Promise { - return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsRetrieve({ - instanceUuid: pk, - }); + return new ManagedApi(DEFAULT_CONFIG) + .managedBlueprintsRetrieve({ + instanceUuid: pk, + }) + .then((inst) => { + if (inst.path.startsWith("oci://")) { + this.source = blueprintSource.oci; + } + return inst; + }); } getSuccessMessage(): string { @@ -31,6 +50,18 @@ export class BlueprintForm extends ModelForm { } } + static get styles(): CSSResult[] { + return super.styles.concat( + PFToggleGroup, + PFContent, + css` + .pf-c-toggle-group { + justify-content: center; + } + `, + ); + } + send = (data: BlueprintInstance): Promise => { if (this.instance?.pk) { return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsUpdate({ @@ -65,27 +96,94 @@ export class BlueprintForm extends ModelForm {

${t`Disabled blueprints are never applied.`}

- - - +
+
+
+
+ +
+ +
+ +
+
+
+ +
+ ${t`Additional settings`}
diff --git a/website/developer-docs/blueprints/index.md b/website/developer-docs/blueprints/index.md index f72257f35..6095bd810 100644 --- a/website/developer-docs/blueprints/index.md +++ b/website/developer-docs/blueprints/index.md @@ -33,7 +33,7 @@ To disable existing blueprints, an empty file can be mounted over the existing b Blueprints can also be stored in remote [OCI](https://opencontainers.org/) compliant registries. This includes GitHub Container Registry, Docker hub and many other registries. -To download a blueprint via OCI, set the path to `https://ghcr.io//:`. This will fetch the blueprint from an OCI package hosted on GHCR. +To download a blueprint via OCI, set the path to `oci://ghcr.io//:`. This will fetch the blueprint from an OCI package hosted on GHCR. To fetch blueprints from a private registry with authentication, credentials can be embedded into the URL. diff --git a/website/docs/releases/v2022.12.md b/website/docs/releases/v2022.12.md index 85dd8e2d0..46b8a5056 100644 --- a/website/docs/releases/v2022.12.md +++ b/website/docs/releases/v2022.12.md @@ -3,6 +3,12 @@ title: Release 2022.12 slug: "2022.12" --- +## Breaking changes + +- Blueprints fetched via OCI require oci:// schema + + To better detect if a blueprint should be fetched locally or via OCI, all OCI sourced blueprints require an `oci://` protocol. + ## New features - Bundled GeoIP City database