reverse proxy works partially now

why
Johannes Bülow 2024-01-27 11:20:40 +01:00
parent f26ffb2d04
commit 6011a0ab81
Signed by untrusted user who does not match committer: jmb
GPG Key ID: B56971CF7B8F83A6
24 changed files with 2308 additions and 0 deletions

46
.air.toml Normal file
View File

@ -0,0 +1,46 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./podterminal"
cmd = "go build -o ./podterminal ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

View File

@ -0,0 +1 @@
{"dependencies":[["vagrant-gatling-rsync",["= 1.0.1"]],["racc",["~> 1.4"]],["nokogiri",["~> 1.6"]],["diffy",[">= 0"]],["rexml",[">= 0"]],["xml-simple",[">= 0"]],["formatador",[">= 0.2","< 2.0"]],["excon",["~> 0.71"]],["mime-types-data",["~> 3.2015"]],["mime-types",[">= 0"]],["builder",[">= 0"]],["fog-core",["~> 2"]],["json",[">= 0"]],["ruby-libvirt",[">= 0.7.0"]],["fog-xml",["~> 0.1.1"]],["multi_json",["~> 1.10"]],["fog-json",[">= 0"]],["fog-libvirt",[">= 0.6.0"]],["vagrant-libvirt",["> 0"]],["vagrant-vmware-desktop",["= 3.0.3"]]],"checksum":"ecefdc74b1ece46a57e6fe697818d99e471dda33f87df8d2c89f932c66d9061e","vagrant_version":"2.3.7"}

View File

@ -0,0 +1 @@
1.5:64023868-3b24-4419-8332-f3d7b66f236a

View File

@ -0,0 +1 @@
{"name":"debian/bookworm64","version":"12.20231211.1","provider":"libvirt","directory":"boxes/debian-VAGRANTSLASH-bookworm64/12.20231211.1/libvirt"}

View File

@ -0,0 +1 @@
5533801d-70e3-4c21-9942-82d20930c789

View File

@ -0,0 +1 @@
1000

View File

@ -0,0 +1 @@
64023868-3b24-4419-8332-f3d7b66f236a

View File

@ -0,0 +1 @@
d9d61f9953294fda9ec8ddc4af7845ac

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAytq06M3nAd1tFrjFWuqvFPczyP5p/aDTMao234C4LX/sebO2
BS+NUcuCboLDk0sfiyJaFWRJuzZFNIrUDabSEuJCSjzN3oDqDKlTF5fEzx4B8bZa
Er1nKAi/51fVK/tspJTtfRNdQ6CSH7vgXMgFbexHi2VQgfrzSAY8YW+/Whq8lSeq
4gppu1kbTaRSe92drVaXHHdqUoMwPVr9LRijGTGPTpXk10NcvtGPzCqzS8S6SvOG
iyHL1criz9hb+z2N58y1M64tggOFzLRf5CBao71b4310M7sbQqdMGRUAyeCXYqqn
auAWbUFzfAxy9pQajmlD/kNCm8JAAKaK1wJPswIDAQABAoIBABBhth9g1Wl4pMEj
fciYUDhMuFFgflW9oaCOouzMu9Ls1D+FzErB6tMysJ9VDw87j1oQlZ7JoQyt1svl
9DcABFIDFKBjJar01THdkLjEiF/DiBupgr+lrQl2H21C0hPBs6Xc4wrpP+xgsLxA
U1+axZl5bdOrhGNizTfBTSn/OMBBaK/NUUYCyTm+skM6mjONhWPeBkwewNhZK6Wk
W8ihA/YYChgv34YkEE/xQI8eOQXaj2JcAZbUqWUw82MlajD2tuhSu+tQ5I4x79av
KHMHvkLgCCyiqQEogjiZjmV4b06/IESL0AurmTE8nPEc+FCZjLZgrXNcZ3qqIzHn
UCvd0S0CgYEA5NYC1qj54p4wOG6v/GAk/EJ6F9yiKmEOTx70SFhc0nH/NZ5sn93O
UM8x6553Cx8HMRFKttUvyG2GB39fCwqGCXYHfVgfvmT4wsl28cZIszSxMF5jT1Fm
suWK/zGEdLmKkFc83YdNArnYSCC7Q5aUSv/ITlO7jljx6pf6EIUowOUCgYEA4u8m
tjeosH5EVgUmO9XvrcHcB5L6qnlT/N5DCW5qedjlrJutjVX2E6aa/2lHyMXN5du6
wl5PdDCaJ2uehVTMtbUxGLRo4XToOUWzcoJYvYiGR0zzwWUliutIH8YTi3NOEeU8
kT+FAgFYR4uxFS3YhNpJB9n9CLyIOGJ7YNgT/LcCgYB7rR7DnXfQfuZY2ZnLsLrM
i7EpDFmoxePR50znfLpOEsZ32DOlA1/qVNEKIw77t71PS6Uxw26byHXTv4dClGF0
45GQsPwXDsNTo0bhzOSl1iidl6XczIXQ0jaZTc3kuBKniD6hC+sXOhImiWosUUm8
bxl3G9IWUQQOYi0ImK858QKBgESiSdYAfW9rsOVHR2n/aS7nG9HanR9j9Ifc/O9k
SqWxeL08lD/TyMnmsKggwkoxsPUdAJ36ghNFA8p6XQY8QHGQbFnpbnMJtZZkw0IV
tBsWqG32Ex7hpXofcL/TW2Poqqr05t2TFXomx/lTgWpDZGHB1yadwk6bHqPW/TOs
Bld/AoGAPTy9k1qKZoeFJVXyKA726PgZYUYHtUipKVnRJvvDsM1QarvhS5F+Lh3U
kcH9QIgFGCp+u7lxDnBLpNto/AvYJmzOUMngu2DsaMDXH6VJf9/Xb7ud2hUYznJq
d8W9yEdN+cth+EMrhaFJrX+bMvnocaWH7rgmWklVeeH1goU+Bh0=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
{"rsync":{"/usr/local/src/podterminal":{"type":"rsync","rsync__auto":true,"guestpath":"/usr/local/src/podterminal","hostpath":"/home/johannes/git/go/podterminal","disabled":false,"__vagrantfile":true,"auto":true,"owner":"vagrant","group":"vagrant"}}}

View File

@ -0,0 +1 @@
/home/johannes/git/go/podterminal

View File

@ -0,0 +1,9 @@
# This file loads the proper rgloader/loader.rb file that comes packaged
# with Vagrant so that encoded files can properly run with Vagrant.
if ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]
require File.expand_path(
"rgloader/loader", ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"])
else
raise "Encoded files can't be read outside of the Vagrant installer."
end

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
release: deps
CGO_ENABLED=1 go build -v -x -buildvcs=true .
dev:
go build .
./podterminal
clean:
rm -f filegate
# rm -f config.yaml
rm -f db.sqlite
rm -rf storage/
deps:
go mod download
go mod tidy

123
Vagrantfile vendored Normal file
View File

@ -0,0 +1,123 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "debian/bookworm64"
config.vm.hostname = "podterminal"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Disable the default share of the current code directory. Doing this
# provides improved isolation between the vagrant box and your host
# by making sure your Vagrantfile isn't accessable to the vagrant box.
# If you use this you may want to enable additional shared subfolders as
# shown above.
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder ".", "/usr/local/src/podterminal", type: "rsync", rsync__auto: true
# Configure the window for gatling to coalesce writes.
if Vagrant.has_plugin?("vagrant-gatling-rsync")
config.gatling.latency = 2.5
config.gatling.time_format = "%H:%M:%S"
end
# Automatically sync when machines with rsync folders come up.
config.gatling.rsync_on_startup = true
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# View the documentation for the provider you are using for more
# information on available options.
config.vm.provider "virtualbox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = true
# Customize the amount of memory on the VM:
vb.memory = "4096"
vb.cpus = 4
end
config.vm.provider "libvirt" do |lv|
lv.memory = "4096"
lv.cpus = 4
end
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL
config.vm.provision "shell", inline: <<-SHELL
# OS
apt-get update
apt-get upgrade -y
apt-get install -y vim curl git wget qemu-guest-agent
apt-get install -y nfs-common podman pwgen open-vm-tools make gcc libgpgme-dev
apt-get install -y build-essential pkgconf pkgconf-bin libdevmapper-dev libbtrfs-dev
echo "export EDITOR=vim" >> /etc/profile
useradd -r -s /bin/false podterminal
## NEOVIM
#wget -O /usr/local/bin/nvim https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
#chmod 755 /usr/local/bin/nvim
#echo "export PATH=$PATH:/usr/local/bin" >> /etc/profile
#git clone https://git.jmbit.de/jmb/nvchad-config
#cd nvchad-config
#make install
#cd ..
#rm -rf nvchad-config
## GOLANG
wget -qO go.tar.gz https://go.dev/dl/go1.21.6.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go.tar.gz
rm go.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> /etc/profile
echo 'CGO_ENABLED=1' >>/etc/profile
echo 'CGO_ENABLED=1' >>/root/.bashrc
export PATH=$PATH:/usr/local/go/bin
go install github.com/cosmtrek/air@latest
SHELL
end

150
go.mod
View File

@ -1,3 +1,153 @@
module git.jmbit.de/jmb/podterminal
go 1.21.5
require (
github.com/containers/podman/v4 v4.8.3
github.com/gin-contrib/sessions v0.0.5
github.com/gin-gonic/gin v1.9.1
github.com/google/uuid v1.4.0
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.12.0-rc.1 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bytedance/sonic v1.10.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cilium/ebpf v0.9.1 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/containerd v1.7.9 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
github.com/containers/buildah v1.33.2 // indirect
github.com/containers/common v0.57.1 // indirect
github.com/containers/image/v5 v5.29.0 // indirect
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/containers/ocicrypt v1.1.9 // indirect
github.com/containers/psgo v1.8.0 // indirect
github.com/containers/storage v1.51.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/disiqueira/gotree/v3 v3.0.2 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-connections v0.4.1-0.20231031175723-0b8c1f4e07a0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/errors v0.20.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/runtime v0.26.0 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/strfmt v0.21.7 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.5 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-containerregistry v0.16.1 // indirect
github.com/google/go-intervals v0.0.2 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/schema v1.2.0 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/sessions v1.2.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.3 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/letsencrypt/boulder v0.0.0-20230213213521-fdfea0d469b6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/sys/mountinfo v0.7.1 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/nxadm/tail v1.4.11 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/opencontainers/runc v1.1.10 // indirect
github.com/opencontainers/runtime-spec v1.1.1-0.20230922153023-c0e90434df2a // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc // indirect
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/sftp v1.13.6 // indirect
github.com/proglottis/gpgme v0.1.3 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect
github.com/sigstore/fulcio v1.4.3 // indirect
github.com/sigstore/rekor v1.2.2 // indirect
github.com/sigstore/sigstore v1.7.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
github.com/sylabs/sif/v2 v2.15.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/vbatts/tar-split v0.11.5 // indirect
github.com/vbauerster/mpb/v8 v8.6.2 // indirect
go.mongodb.org/mongo-driver v1.11.3 // indirect
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface v0.6.2 // indirect
)

1531
go.sum Normal file

File diff suppressed because it is too large Load Diff

26
main.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"log"
"net"
"git.jmbit.de/jmb/podterminal/pods"
"git.jmbit.de/jmb/podterminal/utils"
"git.jmbit.de/jmb/podterminal/web"
)
func main() {
laddr := &net.TCPAddr{
IP: net.IPv4zero,
Port: 80,
}
listener, err := net.ListenTCP("tcp", laddr)
if err != nil {
log.Fatal("could not bind to port 80", err)
}
pods.ConnectSocket()
// Dumm, ich weiß
utils.DropPrivileges("podterminal")
pods.Cleanup()
web.Run(listener)
}

53
pods/container.go Normal file
View File

@ -0,0 +1,53 @@
package pods
import (
"log"
"github.com/containers/podman/v4/pkg/bindings/containers"
"github.com/containers/podman/v4/pkg/specgen"
)
func CreateContainer() (string, error) {
image := "docker.io/linuxserver/webtop"
conn := Socket
envmap := make(map[string]string)
s := specgen.NewSpecGenerator(image, false)
envmap["PASSWORD"] = ""
envmap["TITLE"] = "Pod Terminal"
envmap["PUID"] = "1000"
envmap["GUID"] = "1000"
s.Env = envmap
createResponse, err := containers.CreateWithSpec(conn, s, nil)
return createResponse.ID, err
}
func StartContainer(id string) error {
return containers.Start(Socket, id, nil)
}
func DestroyContainer(id string) error {
conn := Socket
if err := containers.Kill(conn, id, nil); err != nil {
log.Println(err)
return err
}
if _, err := containers.Remove(conn, id, nil); err != nil {
log.Println(err)
return err
}
return nil
}
func GetContainerIP(id string) (string, error) {
conn := Socket
container, err := containers.Inspect(conn, id, nil)
if err != nil {
log.Println(err)
return "", err
}
ip := container.NetworkSettings.IPAddress
return ip, err
}

56
pods/manager.go Normal file
View File

@ -0,0 +1,56 @@
package pods
import (
"context"
"log"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/bindings/containers"
"github.com/containers/podman/v4/pkg/bindings/images"
)
var Socket context.Context
func socketConnection() context.Context {
uri := "unix:///run/podman/podman.sock"
conn, err := bindings.NewConnection(context.Background(), uri)
if err != nil {
log.Fatal(err)
}
return conn
}
func TestPodman() {
_ = socketConnection()
}
func ConnectSocket() {
Socket = socketConnection()
}
func PullImage() {
image := "docker.io/linuxserver/webtop"
conn := Socket
_, err := images.Pull(conn, image, nil)
if err != nil {
log.Println(err)
}
}
func Cleanup() {
containerList, err := containers.List(Socket, nil)
if err != nil {
log.Println(err)
}
for _, container := range containerList {
err = containers.Kill(Socket, container.ID, nil)
if err != nil {
log.Println(err)
}
_, err := containers.Remove(Socket, container.ID, nil)
if err != nil {
log.Println(err)
}
}
}

BIN
tmp/main Executable file

Binary file not shown.

42
utils/dropPrivileges.go Normal file
View File

@ -0,0 +1,42 @@
package utils
import (
"log"
"os/user"
"strconv"
"syscall"
)
func DropPrivileges(username string) {
currentUser, err := user.Current()
if err != nil {
log.Fatal(err)
}
if currentUser.Uid == "0" {
return
}
targetUser, err := user.Lookup(username)
if err != nil {
log.Fatal(err)
}
uid, err := strconv.Atoi(targetUser.Uid)
if err != nil {
log.Fatal(err)
}
gid, err := strconv.Atoi(targetUser.Gid)
if err != nil {
log.Fatal(err)
}
err = syscall.Setuid(uid)
if err != nil {
log.Fatal(err)
}
err = syscall.Setgid(gid)
if err != nil {
log.Fatal(err)
}
}

38
utils/randomString.go Normal file
View File

@ -0,0 +1,38 @@
package utils
import (
"crypto/rand"
"fmt"
"math"
"math/big"
)
type CustomError struct {
Message string
}
func (e *CustomError) Error() string {
return e.Message
}
// RandomString generates a string with the given length using crypt/rand
func RandomString(length int) (string, error) {
if length < 0 {
err := &CustomError{Message: "Length has to be bigger than 0"}
return "", err
}
if length > math.MaxInt32 {
err := &CustomError{Message: fmt.Sprintf("Length has to be bigger than %d", math.MaxInt32)}
return "", err
}
const characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
byteSlice := make([]byte, length)
for i := 0; i < length; i++ {
randomInt, err := rand.Int(rand.Reader, big.NewInt(int64(len(characters))))
if err != nil {
return "", err
}
byteSlice[i] = characters[randomInt.Int64()]
}
return string(byteSlice), nil
}

View File

@ -0,0 +1,62 @@
package utils
import (
"math"
"testing"
)
func TestRandomString(t *testing.T) {
t.Run("Test valid length", func(t *testing.T) {
length := 10
result, err := RandomString(length)
if err != nil {
t.Errorf("Expected no error, but got: %v", err)
}
if len(result) != length {
t.Errorf("Expected a string of length %d, but got: %d", length, len(result))
}
})
t.Run("Test zero length", func(t *testing.T) {
length := 0
result, err := RandomString(length)
if err != nil {
t.Errorf("Expected no error, but got: %v", err)
}
if len(result) != length {
t.Errorf("Expected an empty string, but got: %s", result)
}
})
t.Run("Test negative length", func(t *testing.T) {
length := -10
result, err := RandomString(length)
if err == nil {
t.Errorf("Expected an error, but got none")
}
if result != "" {
t.Errorf("Expected an empty string, but got: %s", result)
}
})
t.Run("Test max Int32 Length", func(t *testing.T) {
length := math.MaxInt32
result, err := RandomString(length)
if err != nil {
t.Errorf("Expected no error, but got: %v", err)
}
if len(result) != length {
t.Errorf("Expected an empty string, but got: %s", result)
}
})
}

117
web/router.go Normal file
View File

@ -0,0 +1,117 @@
package web
import (
"fmt"
"log"
"net"
"net/http/httputil"
"net/url"
"time"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"git.jmbit.de/jmb/podterminal/pods"
)
var proxies = make(map[string]*httputil.ReverseProxy)
func Run(listener net.Listener) error {
router := setupRouter()
err := router.RunListener(listener)
if err != nil {
return err
}
return nil
}
func setupRouter() *gin.Engine {
gin.ForceConsoleColor()
gin.SetMode("release")
router := gin.New()
store := cookie.NewStore([]byte(uuid.NewString()))
router.Use(gin.Recovery())
router.Use(sessions.Sessions("session", store))
router.Use(urlLog())
router.Any("/", containerProxy)
return router
}
func urlLog() gin.HandlerFunc {
return func(c *gin.Context) {
log.Printf(
"[INFO] %s: %s: %s",
c.Request.RemoteAddr,
c.Request.Method,
c.Request.URL,
)
}
}
func createReverseProxy(backendService string) (*httputil.ReverseProxy, error) {
var err error
backendURL, err := url.Parse(backendService)
if err != nil {
log.Printf("Could not parees backend URL: %v", err)
}
proxy := &httputil.ReverseProxy{
Rewrite: func(request *httputil.ProxyRequest) {
request.SetURL(backendURL)
request.Out.Host = request.In.Host
},
}
return proxy, err
}
func containerProxy(c *gin.Context) {
session := sessions.Default(c)
if session.Get("ct") == nil {
ct, err := pods.CreateContainer()
if err != nil {
c.HTML(500, "Error", fmt.Sprintf("Could not create Container: %v", err))
c.Abort()
}
err = pods.StartContainer(ct)
if err != nil {
c.HTML(500, "Error", fmt.Sprintf("Could not start Container: %v", err))
c.Abort()
}
// Hack to wait for Container to start up and get assigned an IP
time.Sleep(1 * time.Second)
ctip, err := pods.GetContainerIP(ct)
if err != nil {
c.HTML(500, "Error", fmt.Sprintf("Could not get Container ip: %v", err))
c.Abort()
}
proxies[ct], err = createReverseProxy(fmt.Sprintf("http://%s:3000", ctip))
if err != nil {
c.HTML(500, "Error", fmt.Sprintf("Could not create Container Proxy: %v", err))
c.Abort()
}
session.Set("ct", ct)
session.Save()
c.Redirect(301, "/")
} else {
sessionID := session.Get("ct")
switch sessionID.(type) {
case string:
default:
c.HTML(500, "Error", "SessionID is not a string")
c.Abort()
}
id := session.Get("ct").(string)
proxy := proxies[id]
proxy.ServeHTTP(c.Writer, c.Request)
}
}