diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..11dcf22 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,93 @@ +name: Build and deploy +on: + push: + branches: + - master + - feature/** + tags: + - v*.*.* + +env: + OCI_REPO: git.huizinga.dev/dreaded_x/${{ gitea.event.repository.name}} + +jobs: + build: + name: Build container and manifests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get Git commit timestamps + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV + + - name: Login to registry + uses: docker/login-action@v3 + with: + registry: git.huizinga.dev + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Install kustomize + run: | + curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash + + - name: Setup Flux CLI + uses: https://github.com/fluxcd/flux2/action@main + with: + version: v2.5.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.OCI_REPO }} + tags: | + type=edge + type=ref,event=branch + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} + + - name: Build and export to docker + id: build + uses: docker/build-push-action@v6 + with: + context: . + load: true + annotations: ${{ steps.meta.outputs.annotations }} + cache-from: type=gha + cache-to: type=gha,mode=max + env: + SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} + + - name: Push container + uses: docker/build-push-action@v6 + id: push + with: + context: . + push: true + sbom: true + provenance: mode=max + tags: ${{ steps.meta.outputs.tags }} + annotations: ${{ steps.meta.outputs.annotations }} + env: + SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} + + - name: Kustomize manifests + run: | + ./kustomize build ./manifests | sed "s/\${DIGEST}/${{ steps.push.outputs.digest }}/" > ./manifests.yaml + + - name: Push manifests + run: | + flux push artifact oci://$OCI_REPO/manifests:latest \ + --path="./manifests.yaml" \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git rev-parse HEAD)" \ + $(echo "${{ steps.meta.outputs.labels }}" | sed -e 's/^/-a /') + + flux tag artifact oci://$OCI_REPO/manifests:latest \ + $(echo "${{ steps.meta.outputs.tags }}" | sed -e 's/^.*:/--tag /') diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 66730c7..5e5b5e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,6 +45,7 @@ repos: name: audit description: Audit packages entry: cargo audit + args: ["--deny", "warnings"] language: system pass_filenames: false verbose: true diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..1e75cb8 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,7 @@ +creation_rules: + - path_regex: .*.yaml + encrypted_regex: ^(data|stringData)$ + key_groups: + - pgp: + - 1E0CF38FF7C9ADAED58B436ABA4A3D3607E5BA8E + - 49F10679C425233EFB4B1B6F9D641BEFA42DEC28 diff --git a/Cargo.lock b/Cargo.lock index 4d1c694..50e7612 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3091,9 +3091,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 9be9e7e..1e4a9e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ ratatui = { version = "0.29.0", features = ["unstable-backend-writer"] } reqwest = { version = "0.12.15", features = ["rustls-tls"] } russh = "0.51.1" thiserror = "2.0.12" -tokio = { version = "1.44.1", features = ["full"] } +tokio = { version = "1.44.2", features = ["full"] } tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["json", "env-filter"] } unicode-width = "0.2.0" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2238ac8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM rust:1.85 AS base +ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse +RUN cargo install cargo-chef --locked --version 0.1.71 && \ + cargo install cargo-auditable --locked --version 0.6.6 +WORKDIR /app + +FROM base AS planner +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM base AS builder +COPY --from=planner /app/recipe.json recipe.json +ENV RUSTC_BOOTSTRAP=1 +RUN cargo chef cook --release --recipe-path recipe.json + +COPY . . +ENV RUSTC_BOOTSTRAP=1 +RUN cargo auditable build --release + +FROM gcr.io/distroless/cc-debian12:nonroot AS runtime +COPY --from=builder /app/target/release/tunnel_rs /tunnel_rs +CMD ["/tunnel_rs"] diff --git a/manifests/certificate.yaml b/manifests/certificate.yaml new file mode 100644 index 0000000..b5cc59b --- /dev/null +++ b/manifests/certificate.yaml @@ -0,0 +1,13 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: tunnel +spec: + secretName: tunnel-tls + issuerRef: + name: letsencrypt + kind: ClusterIssuer + commonName: "*.tunnel.${domain}" + dnsNames: + - "tunnel.${domain}" + - "*.tunnel.${domain}" diff --git a/manifests/deployment.yaml b/manifests/deployment.yaml new file mode 100644 index 0000000..f7b5505 --- /dev/null +++ b/manifests/deployment.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tunnel + labels: + app: tunnel + app.kubernetes.io/name: tunnel +spec: + replicas: 1 + selector: + matchLabels: + app: tunnel + template: + metadata: + labels: + app: tunnel + annotations: + kubectl.kubernetes.io/default-container: tunnel + spec: + containers: + - name: tunnel + image: git.huizinga.dev/dreaded_x/tunnel_rs@${DIGEST} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 50m + memory: 100Mi + ports: + - containerPort: 3000 + - containerPort: 2222 + volumeMounts: + - name: credentials + readOnly: true + mountPath: "/secrets/credentials" + - name: key + readOnly: true + mountPath: "/secrets/key" + env: + - name: RUST_LOG + value: info,tunnel_rs=debug + - name: TUNNEL_DOMAIN + value: tunnel.${domain} + - name: AUTHZ_ENDPOINT + value: http://authelia.authelia.svc.cluster.local/api/authz/forward-auth + - name: LDAP_ADDRESS + value: ldap://lldap.lldap.svc.cluster.local:3890 + - name: LDAP_BASE + value: ou=people,dc=huizinga,dc=dev + - name: LDAP_BIND_DN + value: uid=tunnel.tunnel,ou=people,dc=huizinga,dc=dev + - name: LDAP_PASSWORD_FILE + value: /secrets/credentials/password + - name: PRIVATE_KEY_FILE + value: /secrets/key/private.pem + volumes: + - name: credentials + secret: + secretName: tunnel-lldap-credentials + + - name: key + secret: + secretName: tunnel-key diff --git a/manifests/ingress-route.yaml b/manifests/ingress-route.yaml new file mode 100644 index 0000000..4a3e3ea --- /dev/null +++ b/manifests/ingress-route.yaml @@ -0,0 +1,15 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: tunnel +spec: + entryPoints: + - websecure + routes: + - match: HostRegexp(`{tunnel:.+}.tunnel.${domain}`) + kind: Rule + services: + - name: tunnel + port: 3000 + tls: + secretName: tunnel-tls diff --git a/manifests/kustomization.yaml b/manifests/kustomization.yaml new file mode 100644 index 0000000..bbbadc3 --- /dev/null +++ b/manifests/kustomization.yaml @@ -0,0 +1,11 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: tunnel +resources: + - ./namespace.yaml + - ./service-user.yaml + - ./secret-tunnel-key.yaml + - ./deployment.yaml + - ./service.yaml + - ./certificate.yaml + - ./ingress-route.yaml diff --git a/manifests/namespace.yaml b/manifests/namespace.yaml new file mode 100644 index 0000000..f0ac212 --- /dev/null +++ b/manifests/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: tunnel diff --git a/manifests/secret-tunnel-key.yaml b/manifests/secret-tunnel-key.yaml new file mode 100644 index 0000000..84d2379 --- /dev/null +++ b/manifests/secret-tunnel-key.yaml @@ -0,0 +1,59 @@ +apiVersion: v1 +kind: Secret +metadata: + name: tunnel-key +type: Opaque +stringData: + private.pem: ENC[AES256_GCM,data:9chbnKvGVtGEHTytURAK03ewcy+2LO3JLN6uCD6EtovQqAHZvBJFmUWDwSKXXLAoH8ErQ7VjldzaGPNhCqJaF/+69N9ruoOELR/NdqBbeXxQLdzNO95qlFGNbvBQaJheuQmT0BIqMxu8GHEjoswdHiE0wQebbJubPu3x85tLu24T86sUpeBuRcFsdouBPCO3q3h5Prdxscl/McTcdB+DE21Mpk0dw9GvxmyeTWg1LAbmtYv5vhdJRCSQW1EtQQNn/o/K3/7ALoGsekomjAoFmVG7OKIwaUbfJkVxyYN8UQ7Q4YQ3C16NCysoNx4aB9AlcvIeME/eNJ+nAQMWFA5q2ewhza+idw1H9GmBJaoIFCGsXXdPTyEglFFf5xGZR/lHGxxD1UP0Zd/b25dIKkAYBnYVPojN1HLom+3dG+Ci1oGQmDkT91w1Zj72b9uIdT+xNTBG7b8bkBlLprUJ8VYm2sGZiFmzYkJd6slwVJ+j0Y26iEEpvPb63stkhkeSIeg1fKSL,iv:lz3hiOS/+xYJ4/ooITqxXNlpZsiA+UXQH+4UTofj2p0=,tag:Pwz3pCqJkSUFx5JflKJJEw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2025-04-14T22:32:45Z" + mac: ENC[AES256_GCM,data:KGxVfxRVzyzkJTfGzVsWzLMDPBhElcpbgeHalctly14MhzsubEVPwr6Qlj4dh2714Vs0NUo3xERbIeLYRZqbqIQkVkXM31bzA0Tsud+Wapv92B9Z2yr249YX1EhxwnFzSR+180vkIB+Vc8n2hfgSXftUg5L5QEouUuilUiXWQKo=,iv:pal8Fypc6HnTnHulaFvo8A5FH6wjdDQQJGUb0G+w6Do=,tag:D4swtLKJctkyDTfMQpdGtg==,type:str] + pgp: + - created_at: "2025-04-14T16:11:54Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA7pKPTYH5bqOAQ/+NeM4vp2r4YXdBgjucZTXcD04WtLEq8rcBlK5naAoiMlN + 4tKfKDDB6UO46An+hJDfIYcMp1PnXw6TxUSxrpyXQadXb6qu9lTow8QuMSMs5tO9 + WmapcoFO9VnXkehC1ObqaZuWgNL/ksA/AF605Pl9ZsdKSgc9CHL7uPpLp6EiC8h7 + /fAjwEnQsw8NbcAsyfJW9GJvrQpisFk1HPxv7d7v1zBO/Jm9otbSSejw1hEFdZcd + AB47XeYzmUJMWC4EVydk6pJhyEEKi3Dv5SrLq7tDSKqxF3wFEQcS2vbORKExzpeh + 7mobTyavdWnT8oVWrnaNXtaCHyEQu58vAlpuL+WlzuPFCooMhlcI9FDceJ/k//MA + rIPt0xjWYqkHMhYLC41F61os1MFPdAJWa37kdJnL/jNjPB1CNKfTSvBZ3uJduOjP + VPQTKr5kne+W9CuE2zildbk3sq2RGNYgRKTNN2cLRPAtQYi75MgCyCACZKJ9kbR1 + 6tFhzWWoyOsiP+ykdWzpSnHTlJqFcV2GUhyCrNk3yRS2eN7e3akM/A5G7cHPiu+C + 1Wt2ZK/df+5Hsj81DHllh2Iir73ezNIqhNisQFciQ2NuCs/42InuM4/CipDoZyBN + 0FZz2E6fq6pupJE6nSklrEam9gg7x4pjF6Mhf2XLEpcWDzFIp956AHKMLIIXnpLU + ZgEJAhBdSWPQYaen46bkYKothIoL9ptVwZLRS4uEDNotJPKZbyfLGdCOIz1pbgQS + xj5nWZSgfDs5yj6NqwsJU7tjaxnGP+qS38fY7ez8tfUk7vZlqY2xRRAthfkhbn4T + lpuph/Pj0Q== + =Jee/ + -----END PGP MESSAGE----- + fp: 1E0CF38FF7C9ADAED58B436ABA4A3D3607E5BA8E + - created_at: "2025-04-14T16:11:54Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA51kG++kLewoAQ/+KZeOjQHSNPw0DI0EPi6juGISmCk24z93THbDVn1KSdm0 + jtLhAIXTKMqTRFuj9m1GFqIXgsmYjQoR5fmDyhzW9ecjyBxMP08qFp4Z7HOO97rM + 3DEe8REiZOyrFyvCr51RzQtmtmULlquzvbzmEwy8CaUaIMpQdOmh2mXyHgX/lYL4 + xqjkkSb64K4fOHKNo08cPBFN9eZtK0Slk09shGx6tS8I2fzpnKEPmgIBpKbuZhtJ + 9MZ5zafiz+339yTQ/y83ZI9o8mNC0fiK8SZhSiIaFVYBzec6FspmkTUSq9wl+7n8 + ZnT01A4UxyaDxmam4g1BK5y9eE8U8MB7op9xv6RjDlQdjOFwehnKUJ5wITjRvj9y + yPvmDYXzOlg15IRGPQdeCTt0GCEF/cdIM+vOLojE6hVDmy5pbOfjoegb/ue9VV3W + KRgj+tlQYKfa0vVCHC3bd1NsXr9eQJtIaQeAcuf5b+TKJn7x1ZwJ/CUQ5NJdTbsF + lRzFwemVijswOdZGGjYiBMA8/7Ql29xeQIzVZiEjU18APDvY9p37kozXRUzvf+3+ + vjASmJICfZSptYYwA6uucpJIhyss9MXhY1/eX8brl4IsKOupX8XeCGnF5JAlYpD8 + JsGFHuZPeKsqyFg5wVjnag3KUx++dqT7a/cgOQ+F2gstnfLJRwa3tMSoY8gVm7DS + XAHMCjfirTv5fO/7txioKFL/INxDXK8Heu+SLdyo2XA2zx3JwYmzVs4UbtkbXo2u + 5NzCQMOVjI+Nq8niqdeV6YCAy/RwrG2ziZP3nNlP3iB3+g5KFmxTot4hFOec + =ckBd + -----END PGP MESSAGE----- + fp: 49F10679C425233EFB4B1B6F9D641BEFA42DEC28 + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/manifests/service-user.yaml b/manifests/service-user.yaml new file mode 100644 index 0000000..b5d72a8 --- /dev/null +++ b/manifests/service-user.yaml @@ -0,0 +1,5 @@ +apiVersion: lldap.huizinga.dev/v1 +kind: ServiceUser +metadata: + name: tunnel +spec: {} diff --git a/manifests/service.yaml b/manifests/service.yaml new file mode 100644 index 0000000..ef2c578 --- /dev/null +++ b/manifests/service.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Service +metadata: + name: tunnel +spec: + ports: + - name: "3000" + port: 3000 + targetPort: 3000 + selector: + app: tunnel +--- +apiVersion: v1 +kind: Service +metadata: + name: tunnel-ssh +spec: + type: LoadBalancer + ports: + - name: "2222" + port: 2222 + targetPort: 2222 + selector: + app: tunnel diff --git a/src/lib.rs b/src/lib.rs index 1ec86c9..4e05d1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(impl_trait_in_fn_trait_return)] #![feature(let_chains)] mod animals; mod auth;