From ed71ed1537778c79ff58b8198f4c3ad103affe98 Mon Sep 17 00:00:00 2001 From: Ilya Sosnovsky Date: Thu, 21 Oct 2021 13:01:03 +0300 Subject: [PATCH] envvar configuraion; arm build; docs fixes --- .github/workflows/publish-latest.yaml | 6 +-- .github/workflows/publish-tag.yaml | 4 +- .github/workflows/release.yaml | 6 +-- .github/workflows/release_arm.yaml | 28 +++++++++++ .gitignore | 8 ++-- Dockerfile | 2 +- Dockerfile.openvpn | 2 +- README.md | 24 ++++++---- build.sh | 2 - build_arm.sh | 18 +++++++ docker-compose.yaml | 12 ++++- install-deps-arm.sh | 13 ++++++ install-deps.sh | 6 +-- main.go | 67 +++++++++++++++------------ 14 files changed, 136 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/release_arm.yaml create mode 100755 build_arm.sh create mode 100755 install-deps-arm.sh diff --git a/.github/workflows/publish-latest.yaml b/.github/workflows/publish-latest.yaml index 5f09ebe..bc986e2 100644 --- a/.github/workflows/publish-latest.yaml +++ b/.github/workflows/publish-latest.yaml @@ -1,8 +1,8 @@ -name: Build and publish to Docker Hub (releases only) -on: +name: Build and publish latest tag to Docker Hub (releases only) +on: release: types: [created] - + jobs: build: name: build latest images for relase diff --git a/.github/workflows/publish-tag.yaml b/.github/workflows/publish-tag.yaml index 5047655..05eb739 100644 --- a/.github/workflows/publish-tag.yaml +++ b/.github/workflows/publish-tag.yaml @@ -1,9 +1,9 @@ -name: Build and publish to Docker Hub (tags only) +name: Build and publish tags to Docker Hub (tags only) on: push: tags: - '*' - + jobs: build: name: build images for tag diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6594d45..f5ae993 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,3 +1,4 @@ +name: Build and publish binaries (releases only) on: release: types: [created] @@ -10,9 +11,8 @@ jobs: CGO_ENABLED: 1 strategy: matrix: - # build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/386, darwin/amd64 goos: [linux] - goarch: ["386", amd64] + goarch: ["386", "amd64"] steps: - name: checkout code uses: actions/checkout@v2 @@ -25,4 +25,4 @@ jobs: ldflags: '-linkmode external -extldflags "-static" -s -w' pre_command: bash ./install-deps.sh binary_name: "ovpn-admin" - asset_name: ovpn-admin-${{ matrix.goos }}-${{ matrix.goarch }}. + asset_name: ovpn-admin-${{ matrix.goos }}-${{ matrix.goarch }} diff --git a/.github/workflows/release_arm.yaml b/.github/workflows/release_arm.yaml new file mode 100644 index 0000000..c17b50f --- /dev/null +++ b/.github/workflows/release_arm.yaml @@ -0,0 +1,28 @@ +name: Build and publish arm binaries (releases only) +on: + release: + types: [created] + +jobs: + releases-matrix: + name: Release Go Binary + runs-on: ubuntu-latest + env: + CGO_ENABLED: 1 + strategy: + matrix: + goos: [linux] + goarch: ["arm", "arm64"] + steps: + - name: checkout code + uses: actions/checkout@v2 + - name: build binaries + uses: wangyoucao577/go-release-action@v1.20 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + goos: ${{ matrix.goos }} + goarch: ${{ matrix.goarch }} + build_command: bash ./build_arm.sh + pre_command: bash ./install-deps_arm.sh + binary_name: "ovpn-admin" + asset_name: ovpn-admin-${{ matrix.goos }}-${{ matrix.goarch }} diff --git a/.gitignore b/.gitignore index 748e1e9..6f8f5aa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,10 @@ easyrsa_slave ccd ccd_master ccd_slave -openvpn-web-ui -openvpn-ui -openvpn-admin -ovpn-admin +openvpn-web-ui* +openvpn-ui* +openvpn-admin* +ovpn-admin* frontend/node_modules main-packr.go diff --git a/Dockerfile b/Dockerfile index bc738bb..13fc4c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,5 +13,5 @@ WORKDIR /app COPY --from=backend-builder /app/ovpn-admin /app RUN apk add --update bash easy-rsa && \ ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \ - wget https://github.com/pashcovich/openvpn-user/releases/download/v1.0.3-rc.1/openvpn-user-linux-amd64.tar.gz -O - | tar xz -C /usr/local/bin && \ + wget https://github.com/pashcovich/openvpn-user/releases/download/v1.0.3/openvpn-user-linux-amd64.tar.gz -O - | tar xz -C /usr/local/bin && \ rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* diff --git a/Dockerfile.openvpn b/Dockerfile.openvpn index ee5f785..ef58b23 100644 --- a/Dockerfile.openvpn +++ b/Dockerfile.openvpn @@ -1,7 +1,7 @@ FROM alpine:3.13 RUN apk add --update bash openvpn easy-rsa && \ ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \ - wget https://github.com/pashcovich/openvpn-user/releases/download/v1.0.3-rc.1/openvpn-user-linux-amd64.tar.gz -O - | tar xz -C /usr/local/bin && \ + wget https://github.com/pashcovich/openvpn-user/releases/download/v1.0.3/openvpn-user-linux-amd64.tar.gz -O - | tar xz -C /usr/local/bin && \ rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* COPY setup/ /etc/openvpn/setup RUN chmod +x /etc/openvpn/setup/configure.sh diff --git a/README.md b/README.md index c7571ad..21cbe2c 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,13 @@ cd ovpn-admin ### 3. Prebuilt binary (WIP) + You can also download and use prebuilt binaries from the [releases](https://github.com/flant/ovpn-admin/releases) page — just choose a relevant tar.gz file. + +### +If you want to use password auth (`--auth` flag) you have to install [openvpn-user](https://github.com/pashcovich/openvpn-user/releases) - just make it available throw PATH variable and don`t forget about execution rights on the binary + ## Usage ``` @@ -83,32 +88,31 @@ Flags: --master.sync-frequency=600 master host data sync frequency in seconds. --master.sync-token=TOKEN master host data sync security token --ovpn.network="172.16.100.0/24" - network for openvpn server + NETWORK/MASK_PREFIX for openvpn server --ovpn.server=HOST:PORT:PROTOCOL ... - comma separated addresses for openvpn servers - --ovpn.server.behindLB ovpn behind cloud loadbalancer + HOST:PORT:PROTOCOL for openvpn server. multiple values + --ovpn.server.behindLB ovpn behind k8s loadbalancer --ovpn.service="openvpn-external" - ovpn behind cloud loadbalancer k8s service name - + ovpn behind k8s service with type load balancer name --mgmt=main=127.0.0.1:8989 ... - comma separated (alias=address) for openvpn servers mgmt interfaces + ALIAS=HOST:PORT for openvpn server mgmt interface. multiple values --metrics.path="/metrics" URL path for surfacing collected metrics --easyrsa.path="./easyrsa/" path to easyrsa dir --easyrsa.index-path="./easyrsa/pki/index.txt" path to easyrsa index file. --ccd Enable client-config-dir. --ccd.path="./ccd" path to client-config-dir - --templates.clientconfig-path="" - path to custom client.config.tpl file - --templates.ccd-path="" path to custom ccd.tpl file + --templates.clientconfig-path="" + path to custom client.conf.tpl + --templates.ccd-path="" path to custom ccd.tpl --auth.password Enable additional password authorization. --auth.db="./easyrsa/pki/users.db" Database path fort password authorization. --debug Enable debug mode. --verbose Enable verbose mode. --version Show application version. - ``` +Also you can configure ovpn-admin throw environment variables ## Further information diff --git a/build.sh b/build.sh index 8871ff0..5d34bfd 100755 --- a/build.sh +++ b/build.sh @@ -2,8 +2,6 @@ PATH=$PATH:~/go/bin -#go get -u github.com/gobuffalo/packr/v2/packr2 - cd frontend && npm install && npm run build && cd .. packr2 diff --git a/build_arm.sh b/build_arm.sh new file mode 100755 index 0000000..a8d9369 --- /dev/null +++ b/build_arm.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +PATH=$PATH:~/go/bin + +cd frontend && npm install && npm run build && cd .. + +packr2 + +if [[ "$GOOS" == "linux" ]]; then + if [[ "$GOARCH" == "arm" ]]; then + CC=arm-linux-gnueabi-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -ldflags "-linkmode external -extldflags -static -s -w" $@ + fi + if [[ "$GOARCH" == "arm64" ]]; then + CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-linkmode external -extldflags -static -s -w" $@ + fi +fi + +packr2 clean diff --git a/docker-compose.yaml b/docker-compose.yaml index 3eea317..87fd2f9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,6 +7,9 @@ services: dockerfile: Dockerfile.openvpn image: openvpn:local command: /etc/openvpn/setup/configure.sh + environment: + OVPN_SERVER_NET: "192.168.100.0" + OVPN_SERVER_MASK: "255.255.255.0" cap_add: - NET_ADMIN ports: @@ -19,7 +22,14 @@ services: build: context: . image: ovpn-admin:local - command: /app/ovpn-admin --debug --ovpn.network="172.16.100.0/22" --master.sync-token="TOKEN" --easyrsa.path="/mnt/easyrsa" --easyrsa.index-path="/mnt/easyrsa/pki/index.txt" --ovpn.server="127.0.0.1:7777:tcp" + command: /app/ovpn-admin + environment: + OVPN_DEBUG: "True" + OVPN_VERBOSE: "True" + OVPN_NETWORK: "192.168.100.0/24" + EASYRSA_PATH: "/mnt/easyrsa" + OVPN_SERVER: "127.0.0.1:7777:tcp" + OVPN_INDEX_PATH: "/mnt/easyrsa/pki/index.txt" network_mode: service:openvpn volumes: - ./easyrsa_master:/mnt/easyrsa diff --git a/install-deps-arm.sh b/install-deps-arm.sh new file mode 100755 index 0000000..1fd0fc9 --- /dev/null +++ b/install-deps-arm.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +apt-get update +apt-get install -y curl +apt-get install -y libc6 libc6-dev gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu + +curl -sL https://deb.nodesource.com/setup_14.x | bash - +apt-get install -y nodejs + +PATH=$PATH:~/go/bin + +go get -u github.com/gobuffalo/packr/v2/packr2 + diff --git a/install-deps.sh b/install-deps.sh index 923eb19..16468b9 100755 --- a/install-deps.sh +++ b/install-deps.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash - apt-get update apt-get install -y curl -apt-get install -y gcc-multilib libc6 libc6-dev libc6-dev-i386 +apt-get install -y libc6 libc6-dev libc6-dev-i386 curl -sL https://deb.nodesource.com/setup_14.x | bash - apt-get install -y nodejs @@ -12,6 +11,3 @@ PATH=$PATH:~/go/bin go get -u github.com/gobuffalo/packr/v2/packr2 -cd frontend && npm install && npm run build && cd .. - -packr2 diff --git a/main.go b/main.go index 0fc6669..4c4f53f 100644 --- a/main.go +++ b/main.go @@ -38,42 +38,41 @@ const ( indexTxtDateLayout = "060102150405Z" stringDateFormat = "2006-01-02 15:04:05" ovpnStatusDateLayout = "2006-01-02 15:04:05" + + kubeTokenFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/token" + kubeNamespaceFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" ) var ( - listenHost = kingpin.Flag("listen.host","host for ovpn-admin").Default("0.0.0.0").String() - listenPort = kingpin.Flag("listen.port","port for ovpn-admin").Default("8080").String() - serverRole = kingpin.Flag("role","server role master or slave").Default("master").HintOptions("master", "slave").String() - masterHost = kingpin.Flag("master.host","url for master server").Default("http://127.0.0.1").String() - masterBasicAuthUser = kingpin.Flag("master.basic-auth.user","user for basic auth on master server url").Default("").String() - masterBasicAuthPassword = kingpin.Flag("master.basic-auth.password","password for basic auth on master server url").Default("").String() - masterSyncFrequency = kingpin.Flag("master.sync-frequency", "master host data sync frequency in seconds.").Default("600").Int() - masterSyncToken = kingpin.Flag("master.sync-token", "master host data sync security token").Default("VerySecureToken").PlaceHolder("TOKEN").String() - openvpnNetwork = kingpin.Flag("ovpn.network","network for openvpn server").Default("172.16.100.0/24").String() - openvpnServer = kingpin.Flag("ovpn.server","comma separated addresses for openvpn servers").Default("127.0.0.1:7777:tcp").PlaceHolder("HOST:PORT:PROTOCOL").Strings() - openvpnServerBehindLB = kingpin.Flag("ovpn.server.behindLB","ovpn behind cloud loadbalancer").Default("false").Bool() - openvpnServiceName = kingpin.Flag("ovpn.service","ovpn behind cloud loadbalancer k8s service name").Default("openvpn-external").String() - mgmtAddress = kingpin.Flag("mgmt","comma separated (alias=address) for openvpn servers mgmt interfaces").Default("main=127.0.0.1:8989").Strings() - metricsPath = kingpin.Flag("metrics.path", "URL path for surfacing collected metrics").Default("/metrics").String() - easyrsaDirPath = kingpin.Flag("easyrsa.path", "path to easyrsa dir").Default("./easyrsa/").String() - indexTxtPath = kingpin.Flag("easyrsa.index-path", "path to easyrsa index file.").Default("./easyrsa/pki/index.txt").String() - ccdEnabled = kingpin.Flag("ccd", "Enable client-config-dir.").Default("false").Bool() - ccdDir = kingpin.Flag("ccd.path", "path to client-config-dir").Default("./ccd").String() - clientConfigTemplatePath = kingpin.Flag("templates.clientconfig-path", "path to custom client.conf.tpl").Default("").String() - ccdTemplatePath = kingpin.Flag("templates.ccd-path", "path to custom ccd.tpl").Default("").String() - authByPassword = kingpin.Flag("auth.password", "Enable additional password authorization.").Default("false").Bool() - authDatabase = kingpin.Flag("auth.db", "Database path fort password authorization.").Default("./easyrsa/pki/users.db").String() - debug = kingpin.Flag("debug", "Enable debug mode.").Default("false").Bool() - verbose = kingpin.Flag("verbose", "Enable verbose mode.").Default("false").Bool() + listenHost = kingpin.Flag("listen.host","host for ovpn-admin").Default("0.0.0.0").Envar("OVPN_LISTEN_HOST").String() + listenPort = kingpin.Flag("listen.port","port for ovpn-admin").Default("8080").Envar("OVPN_LISTEN_PROT").String() + serverRole = kingpin.Flag("role","server role master or slave").Default("master").Envar("OVPN_ROLE").HintOptions("master", "slave").String() + masterHost = kingpin.Flag("master.host","url for master server").Default("http://127.0.0.1").Envar("OVPN_MASTER_HOST").String() + masterBasicAuthUser = kingpin.Flag("master.basic-auth.user","user for basic auth on master server url").Default("").Envar("OVPN_MASTER_USER").String() + masterBasicAuthPassword = kingpin.Flag("master.basic-auth.password","password for basic auth on master server url").Default("").Envar("OVPN_MASTER_PASSWORD").String() + masterSyncFrequency = kingpin.Flag("master.sync-frequency", "master host data sync frequency in seconds.").Default("600").Envar("OVPN_MASTER_SYNC_FREQUENCY").Int() + masterSyncToken = kingpin.Flag("master.sync-token", "master host data sync security token").Default("VerySecureToken").Envar("OVPN_MASTER_TOKEN").PlaceHolder("TOKEN").String() + openvpnNetwork = kingpin.Flag("ovpn.network","NETWORK/MASK_PREFIX for openvpn server").Default("172.16.100.0/24").Envar("OVPN_NETWORK").String() + openvpnServer = kingpin.Flag("ovpn.server","HOST:PORT:PROTOCOL for openvpn server. multiple values").Default("127.0.0.1:7777:tcp").Envar("OVPN_SERVER").PlaceHolder("HOST:PORT:PROTOCOL").Strings() + openvpnServerBehindLB = kingpin.Flag("ovpn.server.behindLB","ovpn behind k8s loadbalancer").Default("false").Envar("OVPN_LB").Bool() + openvpnServiceName = kingpin.Flag("ovpn.service","ovpn behind k8s service with type load balancer name").Default("openvpn-external").Envar("OVPN_LB_SERVICE").String() + mgmtAddress = kingpin.Flag("mgmt","ALIAS=HOST:PORT for openvpn server mgmt interface. multiple values").Default("main=127.0.0.1:8989").Envar("OVPN_MGMT").Strings() + metricsPath = kingpin.Flag("metrics.path", "URL path for surfacing collected metrics").Default("/metrics").Envar("OVPN_METRICS_PATH").String() + easyrsaDirPath = kingpin.Flag("easyrsa.path", "path to easyrsa dir").Default("./easyrsa/").Envar("EASYRSA_PATH").String() + indexTxtPath = kingpin.Flag("easyrsa.index-path", "path to easyrsa index file.").Default("./easyrsa/pki/index.txt").Envar("OVPN_INDEX_PATH").String() + ccdEnabled = kingpin.Flag("ccd", "Enable client-config-dir.").Default("false").Envar("OVPN_CCD").Bool() + ccdDir = kingpin.Flag("ccd.path", "path to client-config-dir").Default("./ccd").Envar("OVPN_CCD_PATH").String() + clientConfigTemplatePath = kingpin.Flag("templates.clientconfig-path", "path to custom client.conf.tpl").Default("").Envar("OVPN_TEMPLATES_CCD_PATH").String() + ccdTemplatePath = kingpin.Flag("templates.ccd-path", "path to custom ccd.tpl").Default("").Envar("OVPN_TEMPLATES_CCD_PATH").String() + authByPassword = kingpin.Flag("auth.password", "Enable additional password authorization.").Default("false").Envar("OVPN_AUTH").Bool() + authDatabase = kingpin.Flag("auth.db", "Database path fort password authorization.").Default("./easyrsa/pki/users.db").Envar("OVPN_AUTH_DB_PATH").String() + debug = kingpin.Flag("debug", "Enable debug mode.").Default("false").Envar("OVPN_DEBUG").Bool() + verbose = kingpin.Flag("verbose", "Enable verbose mode.").Default("false").Envar("OVPN_VERBOSE").Bool() certsArchivePath = "/tmp/" + certsArchiveFileName ccdArchivePath = "/tmp/" + ccdArchiveFileName - version = "1.7.0" - - kubeTokenFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/token" - kubeNamespaceFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" - + version = "1.7.4" ) var ( @@ -431,6 +430,14 @@ func main() { go ovpnAdmin.syncWithMaster() } + if *debug { + log.Println("Runnnig in debug mode") + } + + if *verbose { + log.Println("Runnnig in verbose mode") + } + ovpnAdmin.templates = packr.New("template", "./templates") staticBox := packr.New("static", "./frontend/static") @@ -459,7 +466,7 @@ func main() { fmt.Fprintf(w, "pong") }) - fmt.Println("Bind: http://" + *listenHost + ":" + *listenPort) + log.Printf("Bind: http://%s:%s\n", *listenHost, *listenPort) log.Fatal(http.ListenAndServe(*listenHost+":"+*listenPort, nil)) }