Compare commits

..

6 Commits

Author SHA1 Message Date
t.behrendt 7735f363f0 feat: allow proxy provider to reference an outpost to be added to
CI / image check (pull_request) Failing after 6s
CI / install-dependencies (pull_request) Successful in 7m48s
CI / build check (pull_request) Successful in 27s
CI / test (pull_request) Successful in 22s
CI / check lint (pull_request) Successful in 3m8s
CI / check format (pull_request) Successful in 7m29s
2026-05-20 20:37:35 +02:00
t.behrendt e181c97bcc docs: update docs
CI / install-dependencies (pull_request) Successful in 22s
CI / check lint (pull_request) Successful in 28s
CI / test (pull_request) Successful in 23s
CI / build check (pull_request) Successful in 1m47s
CI / check format (pull_request) Successful in 7m18s
CI / image check (pull_request) Failing after 6s
2026-05-19 21:44:42 +02:00
t.behrendt 2d9d6f56aa refactor: consolidate common controller code 2026-05-19 21:44:42 +02:00
t.behrendt fb926c81ee feat: add bare policy binding controller 2026-05-19 21:41:43 +02:00
t.behrendt bd6a71f541 feat: add bare application controller 2026-05-19 21:41:35 +02:00
t.behrendt 442068c1b5 refactor: move proxyprovider controller into dedicated package 2026-05-19 21:16:45 +02:00
9 changed files with 70 additions and 57 deletions
-1
View File
@@ -1,7 +1,6 @@
* *
!pkg !pkg
!internal
!controller.go !controller.go
!main.go !main.go
!go.mod !go.mod
+64 -20
View File
@@ -10,15 +10,48 @@ on:
- "**/*.go" - "**/*.go"
- "Dockerfile" - "Dockerfile"
- "Makefile" - "Makefile"
pull_request:
branches:
- main
workflow_dispatch: workflow_dispatch:
env: env:
DOCKER_REGISTRY: gitea.t000-n.de DOCKER_REGISTRY: gitea.t000-n.de
jobs: jobs:
build_and_push:
name: Build and push
strategy:
matrix:
arch: [amd64]
runs-on:
- ubuntu-latest
- linux_${{ matrix.arch }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Get Metadata
id: meta
run: |
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_OUTPUT
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
file: ./Dockerfile
platforms: linux/${{ matrix.arch }}
push: true
provenance: false
build-args: GOARCH=${{ matrix.arch }}
tags: |
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-${{ matrix.arch }}
create_tag: create_tag:
name: Create tag name: Create tag
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -40,21 +73,32 @@ jobs:
run: | run: |
echo "tag=${{ steps.tag.outputs.new-tag }}" >> $GITHUB_OUTPUT echo "tag=${{ steps.tag.outputs.new-tag }}" >> $GITHUB_OUTPUT
build_and_push_image: create_manifest:
needs: create_tag name: Create manifest
uses: https://gitea.t000-n.de/t.behrendt/gitea-workflows/.gitea/workflows/build-container.yaml@0.1.1 needs:
with: - build_and_push
registry: gitea.t000-n.de/t.behrendt - create_tag
registry-user: ${{ secrets.REGISTRY_USER }} runs-on: ubuntu-latest
registry-password: ${{ secrets.REGISTRY_PASSWORD }} steps:
repo-name: authentik-kubernetes-operator - name: Checkout
tag: ${{ needs.create_tag.outputs.tag }} uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
deploy: - name: Get Metadata
needs: build_and_push_image id: meta
uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/deploy.yaml@1.1.0 run: |
with: echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_OUTPUT
k8s_dir: ./k8s echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
skip_helm_deployment: true
skip_shared_secrets_deployment: true - name: Login to Registry
secrets: inherit uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Create manifest
run: |
docker manifest create ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ needs.create_tag.outputs.tag }} \
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-amd64
docker manifest push ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ needs.create_tag.outputs.tag }}
+1 -1
View File
@@ -20,7 +20,7 @@ codegen:
test: test-unit test-coverage test: test-unit test-coverage
test-unit: test-unit:
go test ./... -coverprofile=coverage.out go test . -coverprofile=coverage.out
test-coverage: test-coverage:
go tool gcov2lcov -infile coverage.out > lcov.info go tool gcov2lcov -infile coverage.out > lcov.info
+3 -3
View File
@@ -34,11 +34,9 @@ spec:
invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184 invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184
# The external host of your application. # The external host of your application.
external_host: https://example.t00n.de external_host: https://example.t00n.de
# The ID of the outpost, which at current point in time can only be retrieved from Authentik directly. In this example: "Proxy-Forward-Auth-Auto"
outpost: e004ffe7-4af6-4ac1-9e9d-522354799e1f
``` ```
The ProxyProvider will be created in Authentik and assigned to the configured outpost. The ProxyProvider will be created in Authentik, but will not be assigned to an outpost or an application (Resources are TBD).
### Application ### Application
@@ -56,6 +54,8 @@ spec:
slug: application-example slug: application-example
# The ID of the provider, which can be retrieved from e.g. the ProxyPRovider via "kubectl get pp proxy-provider-example -o jsonpath='{.status.pk}'" # The ID of the provider, which can be retrieved from e.g. the ProxyPRovider via "kubectl get pp proxy-provider-example -o jsonpath='{.status.pk}'"
provider: 105 provider: 105
# The ID of the outpost, which at current point in time, can only be retrieved from Authentik directly. This value can also not be updated.
outpost: e004ffe7-4af6-4ac1-9e9d-522354799e1f
``` ```
### PolicyBinding ### PolicyBinding
-7
View File
@@ -16,9 +16,6 @@ spec:
- name: PK - name: PK
type: string type: string
jsonPath: .status.pk jsonPath: .status.pk
- name: Outpost
type: string
jsonPath: .spec.outpost
schema: schema:
openAPIV3Schema: openAPIV3Schema:
type: object type: object
@@ -34,15 +31,11 @@ spec:
type: string type: string
external_host: external_host:
type: string type: string
outpost:
type: string
format: uuid
required: required:
- name - name
- authorization_flow - authorization_flow
- invalidation_flow - invalidation_flow
- external_host - external_host
- outpost
status: status:
type: object type: object
properties: properties:
+1 -1
View File
@@ -9,4 +9,4 @@ spec:
authorization_flow: 16896c6d-b326-42d1-8d3f-93f32921962e authorization_flow: 16896c6d-b326-42d1-8d3f-93f32921962e
invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184 invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184
external_host: https://example.t00n.de external_host: https://example.t00n.de
outpost: ce8f74c0-88cd-47fe-96f5-d6507b739ceb outpost: e004ffe7-4af6-4ac1-9e9d-522354799e1f
-1
View File
@@ -1 +0,0 @@
---
+1 -5
View File
@@ -212,12 +212,8 @@ func (c *ProxyProviderController) reconcileUpdate(ctx context.Context, pp *v1alp
if err != nil { if err != nil {
return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyPartialUpdate`: %w with response %v", err, r) return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyPartialUpdate`: %w with response %v", err, r)
} }
pp.Status.PK = strconv.Itoa(int(resp.Pk))
err = c.reconcileOutpost(ctx, pp.Spec.Outpost, int32(pk), ReconcileOutpostModeAdd) pp.Status.PK = strconv.Itoa(int(resp.Pk))
if err != nil {
return fmt.Errorf("error when calling `reconcileOutpost`: %w", err)
}
return c.updateProxyProviderStatus(ctx, pp) return c.updateProxyProviderStatus(ctx, pp)
} }
@@ -123,7 +123,6 @@ func TestController_syncHandler_update(t *testing.T) {
pp.Status.PK = "42" pp.Status.PK = "42"
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer} pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
var outpostPartialUpdateCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{ server := newAuthentikTestServer(t, authentikTestHandlers{
allRetrieve: func(w http.ResponseWriter, _ *http.Request) { allRetrieve: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42}) writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
@@ -131,20 +130,6 @@ func TestController_syncHandler_update(t *testing.T) {
proxyPartialUpdate: func(w http.ResponseWriter, _ *http.Request) { proxyPartialUpdate: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42}) writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
}, },
outpostRetrieve: outpostRetrieveHandler(t, nil),
outpostPartialUpdate: func(w http.ResponseWriter, r *http.Request) {
outpostPartialUpdateCalled = true
var body struct {
Providers []int32 `json:"providers"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode outpost patch body: %v", err)
}
if !slices.Contains(body.Providers, 42) {
t.Fatalf("patched providers = %v, want to contain 42", body.Providers)
}
writeJSON(t, w, http.StatusOK, map[string]any{"pk": testOutpostID, "providers": body.Providers})
},
}) })
t.Cleanup(server.Close) t.Cleanup(server.Close)
@@ -155,9 +140,6 @@ func TestController_syncHandler_update(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("syncHandler() error = %v", err) t.Fatalf("syncHandler() error = %v", err)
} }
if !outpostPartialUpdateCalled {
t.Fatal("expected Authentik outpost partial update call")
}
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name) got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
if got.Status.PK != "42" { if got.Status.PK != "42" {