mirror of
https://github.com/gravitl/netmaker.git
synced 2024-09-21 07:46:04 +08:00
commit
aa821e0304
8
.fpm
Normal file
8
.fpm
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
--name netclient
|
||||||
|
--license sspl
|
||||||
|
--depends wireguard-tools
|
||||||
|
--description "Netmaker's netclient agent and CLI"
|
||||||
|
--url "https//:github.com/gravitl/netmaker"
|
||||||
|
--maintainer "info@gravitl.com"
|
||||||
|
--vendor Gravitl
|
||||||
|
|
72
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
72
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: ["bug", "triage"]
|
||||||
|
assignees: ["ok-john", "0xdcarns", "afeiszli", "mattkasun"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: input
|
||||||
|
id: contact
|
||||||
|
attributes:
|
||||||
|
label: Contact Details
|
||||||
|
description: How can we get in touch with you if we need more info?
|
||||||
|
placeholder: ex. email@example.com
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: Also tell us, what did you expect to happen?
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
value: "A bug happened!"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: What version are you running?
|
||||||
|
options:
|
||||||
|
- v0.12.0
|
||||||
|
- v0.11.1
|
||||||
|
- v0.11.0
|
||||||
|
- v0.10.0
|
||||||
|
- v0.9.4
|
||||||
|
- v0.9.3
|
||||||
|
- v0.9.2
|
||||||
|
- v0.9.1
|
||||||
|
- v0.9.0
|
||||||
|
- v0.8.5
|
||||||
|
- Not sure
|
||||||
|
- Not listed
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: What OS are you using?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- Linux
|
||||||
|
- FreeBSD
|
||||||
|
- Windows
|
||||||
|
- Mac
|
||||||
|
- Unlisted
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant log output
|
||||||
|
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||||
|
render: shell
|
||||||
|
- type: checkboxes
|
||||||
|
id: terms
|
||||||
|
attributes:
|
||||||
|
label: Contributing guidelines
|
||||||
|
description: Have you read [CONTRIBUTING.md](https://github.com/gravitl/netmaker/blob/master/CONTRIBUTING.md)
|
||||||
|
options:
|
||||||
|
- label: Yes, I did.
|
||||||
|
required: true
|
264
.github/workflows/buildandrelease.yml
vendored
264
.github/workflows/buildandrelease.yml
vendored
|
@ -5,16 +5,17 @@ on:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: 'Netmaker version'
|
description: 'Netmaker version'
|
||||||
required: false
|
required: true
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
tag: ${{ steps.echo.outputs.tag }}
|
||||||
|
version: ${{ steps.echo.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Get Version Number
|
- name: Get Version Number
|
||||||
run: |
|
run: |
|
||||||
if [[ -n "${{ github.event.inputs.version }}" ]]; then
|
if [[ -n "${{ github.event.inputs.version }}" ]]; then
|
||||||
|
@ -23,32 +24,43 @@ jobs:
|
||||||
NETMAKER_VERSION=$(curl -fsSL https://api.github.com/repos/gravitl/netmaker/tags | grep 'name' | head -1 | cut -d'"' -f4)
|
NETMAKER_VERSION=$(curl -fsSL https://api.github.com/repos/gravitl/netmaker/tags | grep 'name' | head -1 | cut -d'"' -f4)
|
||||||
fi
|
fi
|
||||||
echo "NETMAKER_VERSION=${NETMAKER_VERSION}" >> $GITHUB_ENV
|
echo "NETMAKER_VERSION=${NETMAKER_VERSION}" >> $GITHUB_ENV
|
||||||
|
# remove everything but digits and . for package (deb, rpm, etc) versions
|
||||||
|
PACKAGE_VERSION=$(echo ${NETMAKER_VERSION} | tr -cd '[:digit:].')
|
||||||
|
echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Echo
|
||||||
|
id: echo
|
||||||
|
run: |
|
||||||
|
echo ${{ env.NETMAKER_VERSION }}
|
||||||
|
echo ${{ env.PACKAGE_VERSION }}
|
||||||
|
if [[ -z ${{ env.NETMAKER_VERSION }} || -z ${{ env.PACKAGE_VERSION }} ]]
|
||||||
|
then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "::set-output name=tag::${{ env.NETMAKER_VERSION }}"
|
||||||
|
echo "::set-output name=version::${{ env.PACKAGE_VERSION }}"
|
||||||
|
netmaker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: set variables
|
||||||
|
run: |
|
||||||
|
echo ${{ needs.version.outputs.tag }} ${{ needs.version.outputs.version }}
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
if [[ -z ${VERSION} || -z ${TAG} ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.17
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netmaker main.go
|
env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netmaker main.go
|
||||||
cd netclient
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm5/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm6/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm7/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm64/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -X 'main.version=$NETMAKER_VERSION'" -o build/netclient-mipsle/netclient main.go && upx build/netclient-mipsle/netclient
|
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags="-X 'main.Version=${NETMAKER_VERSION}'" -o build/netclient-freebsd/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=5 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm5/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=6 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm6/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=7 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm7/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm64/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-darwin/netclient main.go
|
|
||||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-darwin-arm64/netclient main.go
|
|
||||||
|
|
||||||
- name: Upload netmaker x86 to Release
|
- name: Upload netmaker x86 to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -59,7 +71,28 @@ jobs:
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netmaker
|
asset_name: netmaker
|
||||||
|
|
||||||
- name: Upload x86 to Release
|
netclient-x86:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set Variables
|
||||||
|
run: |
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.17
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd netclient
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient main.go
|
||||||
|
- name: Upload netclient x86 to Release
|
||||||
|
continue-on-error: true
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -69,26 +102,100 @@ jobs:
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient
|
asset_name: netclient
|
||||||
|
|
||||||
- name: Upload arm5 to Release
|
- name: Package x86 deb
|
||||||
|
continue-on-error: true
|
||||||
|
uses: gravitl/github-action-fpm@master
|
||||||
|
with:
|
||||||
|
fpm_args: './netclient/build/netclient=/sbin/netclient ./netclient/build/netclient.service=/lib/systemd/system/netclient.service'
|
||||||
|
fpm_opts: '-s dir -t deb --architecture amd64 --version ${{ env.PACKAGE_VERSION }}'
|
||||||
|
- name: Upload x86 deb to Release
|
||||||
|
continue-on-error: true
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: netclient/build/netclient-arm5/netclient
|
file: netclient_${{ env.PACKAGE_VERSION }}_amd64.deb
|
||||||
tag: ${{ env.NETMAKER_VERSION }}
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
asset_name: netclient_${{ env.PACKAGE_VERSION }}_amd64.deb
|
||||||
|
|
||||||
|
- name: Package x86 rpm
|
||||||
|
continue-on-error: true
|
||||||
|
uses: gravitl/github-action-fpm@master
|
||||||
|
with:
|
||||||
|
fpm_args: './netclient/build/netclient=/sbin/netclient ./netclient/build/netclient.service=/lib/systemd/system/netclient.service'
|
||||||
|
fpm_opts: '-s dir -t rpm --architecture amd64 --version ${{ env.PACKAGE_VERSION }}'
|
||||||
|
- name: Upload x86 rpm to Release
|
||||||
|
continue-on-error: true
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: netclient-${{ env.PACKAGE_VERSION }}-1.x86_64.rpm
|
||||||
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
|
overwrite: true
|
||||||
|
prerelease: true
|
||||||
|
asset_name: netclient-${{ env.PACKAGE_VERSION }}-1.x86_64.rpm
|
||||||
|
|
||||||
|
- name: Package x86 pacman
|
||||||
|
continue-on-error: true
|
||||||
|
uses: gravitl/github-action-fpm@master
|
||||||
|
with:
|
||||||
|
# arch has particular path requirements --- cannot write to a symbolic link e.g. /sbin and /lib
|
||||||
|
fpm_args: './netclient/build/netclient=/usr/bin/netclient ./netclient/build/netclient.service=/usr/lib/systemd/system/netclient.service'
|
||||||
|
fpm_opts: '-s dir -t pacman --architecture amd64 --version ${{ env.PACKAGE_VERSION }}'
|
||||||
|
- name: Upload x86 pacman to Release
|
||||||
|
continue-on-error: true
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: netclient-${{ env.PACKAGE_VERSION }}-1-x86_64.pkg.tar.zst
|
||||||
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
|
overwrite: true
|
||||||
|
prerelease: true
|
||||||
|
asset_name: netclient-${{ env.PACKAGE_VERSION }}-1-x86_64.pkg.tar.zst
|
||||||
|
|
||||||
|
netclient-arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set Variables
|
||||||
|
run: |
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.17
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd netclient
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm5/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm6/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm7/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-arm64/netclient main.go
|
||||||
|
- name: Upload arm5 to Release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: netclient/build/netclient-arm5/netclient
|
||||||
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
|
overwrite: true
|
||||||
|
prerelease: true
|
||||||
asset_name: netclient-arm5
|
asset_name: netclient-arm5
|
||||||
|
|
||||||
- name: Upload arm6 to Release
|
- name: Upload arm6 to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: netclient/build/netclient-arm6/netclient
|
file: netclient/build/netclient-arm6/netclient
|
||||||
tag: ${{ env.NETMAKER_VERSION }}
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient-arm6
|
asset_name: netclient-arm6
|
||||||
|
|
||||||
- name: Upload arm7 to Release
|
- name: Upload arm7 to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -98,8 +205,9 @@ jobs:
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient-arm7
|
asset_name: netclient-arm7
|
||||||
|
|
||||||
- name: Upload arm64 to Release
|
- name: Upload arm64 to Release
|
||||||
|
continue-on-error: true
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -108,7 +216,59 @@ jobs:
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient-arm64
|
asset_name: netclient-arm64
|
||||||
|
- name: Package arm64 deb
|
||||||
|
continue-on-error: true
|
||||||
|
uses: gravitl/github-action-fpm@master
|
||||||
|
with:
|
||||||
|
fpm_args: './netclient/build/netclient-arm64/netclient=/sbin/netclient ./netclient/build/netclient.service=/lib/systemd/netclient.service'
|
||||||
|
fpm_opts: '-s dir -t deb --architecture arm64 --version ${{ env.PACKAGE_VERSION }}'
|
||||||
|
- name: Upload arm deb to Release
|
||||||
|
continue-on-error: true
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: netclient_${{ env.PACKAGE_VERSION }}_arm64.deb
|
||||||
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
|
overwrite: true
|
||||||
|
prerelease: true
|
||||||
|
asset_name: netclient_${{ env.PACKAGE_VERSION }}_arm64.deb
|
||||||
|
- name: Package arm64 rpm
|
||||||
|
continue-on-error: true
|
||||||
|
uses: gravitl/github-action-fpm@master
|
||||||
|
with:
|
||||||
|
fpm_args: './netclient/build/netclient-arm64/netclient=/sbin/netclient ./netclient/build/netclient.service=/lib/systemd/netclient.service'
|
||||||
|
fpm_opts: '-s dir -t rpm --architecture arm64 --version ${{ env.PACKAGE_VERSION }}'
|
||||||
|
- name: Upload arm64 rpm to Release
|
||||||
|
continue-on-error: true
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: netclient-${{ env.PACKAGE_VERSION }}-1.aarch64.rpm
|
||||||
|
tag: ${{ env.NETMAKER_VERSION }}
|
||||||
|
overwrite: true
|
||||||
|
prerelease: true
|
||||||
|
asset_name: netclient-${{ env.PACKAGE_VERSION }}-1.aarch4.rpm
|
||||||
|
|
||||||
|
netclient-mipsle:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set Variables
|
||||||
|
run: |
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.17
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd netclient
|
||||||
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -X 'main.version=$NETMAKER_VERSION'" -o build/netclient-mipsle/netclient main.go && upx build/netclient-mipsle/netclient
|
||||||
- name: Upload mipsle to Release
|
- name: Upload mipsle to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -118,6 +278,31 @@ jobs:
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient-mipsle
|
asset_name: netclient-mipsle
|
||||||
|
|
||||||
|
netclient-freebsd:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set Variables
|
||||||
|
run: |
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.17
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd netclient
|
||||||
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags="-X 'main.Version=${NETMAKER_VERSION}'" -o build/netclient-freebsd/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=5 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm5/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=6 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm6/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=7 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm7/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-freebsd-arm64/netclient main.go
|
||||||
|
|
||||||
- name: Upload freebsd to Release
|
- name: Upload freebsd to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
@ -168,8 +353,29 @@ jobs:
|
||||||
overwrite: true
|
overwrite: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
asset_name: netclient-freebsd-arm64
|
asset_name: netclient-freebsd-arm64
|
||||||
|
|
||||||
- name: Upload darwin to Release
|
netclient-darwin:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set Variables
|
||||||
|
run: |
|
||||||
|
TAG=${{needs.version.outputs.tag}}
|
||||||
|
VERSION=${{needs.version.outputs.version}}
|
||||||
|
echo "NETMAKER_VERSION=${TAG}" >> $GITHUB_ENV
|
||||||
|
echo "PACKAGE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.17
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd netclient
|
||||||
|
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-darwin/netclient main.go
|
||||||
|
env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-X 'main.version=${NETMAKER_VERSION}'" -o build/netclient-darwin-arm64/netclient main.go
|
||||||
|
- name: Upload darwin-arm64 to Release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
9
.github/workflows/purgeGHCR.yml
vendored
9
.github/workflows/purgeGHCR.yml
vendored
|
@ -1,8 +1,9 @@
|
||||||
name: Purge untagged images from GHCR
|
name: Purge untagged images from GHCR
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '1 1 1 * *'
|
||||||
jobs:
|
jobs:
|
||||||
purge:
|
purge:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -15,7 +16,7 @@ jobs:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
organization: gravitl
|
organization: gravitl
|
||||||
container: netmaker
|
container: netmaker
|
||||||
dry-run: true # Dry-run first, then change to `false`
|
dry-run: false # Dry-run first, then change to `false`
|
||||||
untagged: true
|
untagged: true
|
||||||
- name: Prune Netclient
|
- name: Prune Netclient
|
||||||
uses: vlaurin/action-ghcr-prune@main
|
uses: vlaurin/action-ghcr-prune@main
|
||||||
|
@ -23,6 +24,6 @@ jobs:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
organization: gravitl
|
organization: gravitl
|
||||||
container: netclient
|
container: netclient
|
||||||
dry-run: true # Dry-run first, then change to `false`
|
dry-run: false # Dry-run first, then change to `false`
|
||||||
untagged: true
|
untagged: true
|
||||||
|
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,6 +6,7 @@ netmaker-amd64
|
||||||
netclient/netclient
|
netclient/netclient
|
||||||
netclient/build
|
netclient/build
|
||||||
netclient/build/
|
netclient/build/
|
||||||
|
!netclient/build/netclient.service
|
||||||
netclient/files/netclient
|
netclient/files/netclient
|
||||||
netclient/netclient-amd64
|
netclient/netclient-amd64
|
||||||
netclient/netclient-arm
|
netclient/netclient-arm
|
||||||
|
@ -14,6 +15,8 @@ netclient/netclient-32
|
||||||
netclient/netclient32
|
netclient/netclient32
|
||||||
netclient/netclient.exe
|
netclient/netclient.exe
|
||||||
config/dnsconfig/
|
config/dnsconfig/
|
||||||
|
controllers/config/dnsconfig/
|
||||||
|
controllers/data/
|
||||||
data/
|
data/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
<img src="netmaker.png" width="75%"><break/>
|
<img src="netmaker.png" width="75%"><break/>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<i>Create and control automated virtual networks.</i>
|
a platform for blazing fast and dynamic virtual networks
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/gravitl/netmaker/releases">
|
<a href="https://github.com/gravitl/netmaker/releases">
|
||||||
<img src="https://img.shields.io/badge/Version-0.11.1-informational?style=flat-square" />
|
<img src="https://img.shields.io/badge/Version-0.12.0-informational?style=flat-square" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/gravitl/netmaker/tags">
|
<a href="https://hub.docker.com/r/gravitl/netmaker/tags">
|
||||||
<img src="https://img.shields.io/docker/pulls/gravitl/netmaker" />
|
<img src="https://img.shields.io/docker/pulls/gravitl/netmaker" />
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.4"
|
||||||
services:
|
services:
|
||||||
netmaker:
|
netmaker:
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes:
|
volumes:
|
||||||
- dnsconfig:/root/config/dnsconfig
|
- dnsconfig:/root/config/dnsconfig
|
||||||
- sqldata:/root/data
|
- sqldata:/root/data
|
||||||
|
@ -45,7 +45,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:v0.11.1
|
image: gravitl/netmaker-ui:v0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.4"
|
||||||
services:
|
services:
|
||||||
netmaker:
|
netmaker:
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes:
|
volumes:
|
||||||
- dnsconfig:/root/config/dnsconfig
|
- dnsconfig:/root/config/dnsconfig
|
||||||
- /usr/bin/wg:/usr/bin/wg
|
- /usr/bin/wg:/usr/bin/wg
|
||||||
|
@ -41,7 +41,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:0.11.1
|
image: gravitl/netmaker-ui:0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.4"
|
||||||
services:
|
services:
|
||||||
netmaker:
|
netmaker:
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes:
|
volumes:
|
||||||
- dnsconfig:/root/config/dnsconfig
|
- dnsconfig:/root/config/dnsconfig
|
||||||
- sqldata:/root/data
|
- sqldata:/root/data
|
||||||
|
@ -45,7 +45,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:v0.11.1
|
image: gravitl/netmaker-ui:v0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.4"
|
||||||
services:
|
services:
|
||||||
netmaker:
|
netmaker:
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes:
|
volumes:
|
||||||
- dnsconfig:/root/config/dnsconfig
|
- dnsconfig:/root/config/dnsconfig
|
||||||
- sqldata:/root/data
|
- sqldata:/root/data
|
||||||
|
@ -45,7 +45,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:v0.11.1
|
image: gravitl/netmaker-ui:v0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -2,7 +2,7 @@ services:
|
||||||
netmaker: # The Primary Server for running Netmaker
|
netmaker: # The Primary Server for running Netmaker
|
||||||
privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on.
|
privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on.
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS)
|
volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS)
|
||||||
- dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration.
|
- dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration.
|
||||||
- sqldata:/root/data
|
- sqldata:/root/data
|
||||||
|
@ -44,7 +44,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:v0.11.1
|
image: gravitl/netmaker-ui:v0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.4"
|
||||||
services:
|
services:
|
||||||
netmaker:
|
netmaker:
|
||||||
container_name: netmaker
|
container_name: netmaker
|
||||||
image: gravitl/netmaker:v0.11.1
|
image: gravitl/netmaker:v0.12.0
|
||||||
volumes:
|
volumes:
|
||||||
- dnsconfig:/root/config/dnsconfig
|
- dnsconfig:/root/config/dnsconfig
|
||||||
- sqldata:/root/data
|
- sqldata:/root/data
|
||||||
|
@ -45,7 +45,7 @@ services:
|
||||||
container_name: netmaker-ui
|
container_name: netmaker-ui
|
||||||
depends_on:
|
depends_on:
|
||||||
- netmaker
|
- netmaker
|
||||||
image: gravitl/netmaker-ui:v0.11.1
|
image: gravitl/netmaker-ui:v0.12.0
|
||||||
links:
|
links:
|
||||||
- "netmaker:api"
|
- "netmaker:api"
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
10.0.0.1 testnode.skynet
|
10.0.0.2 testnode.skynet myhost.skynet
|
||||||
10.0.0.2 myhost.skynet
|
|
||||||
|
|
|
@ -151,9 +151,15 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) {
|
||||||
if network.DefaultExtClientDNS != "" {
|
if network.DefaultExtClientDNS != "" {
|
||||||
defaultDNS = "DNS = " + network.DefaultExtClientDNS
|
defaultDNS = "DNS = " + network.DefaultExtClientDNS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultMTU := 1420
|
||||||
|
if gwnode.MTU != 0 {
|
||||||
|
defaultMTU = int(gwnode.MTU)
|
||||||
|
}
|
||||||
config := fmt.Sprintf(`[Interface]
|
config := fmt.Sprintf(`[Interface]
|
||||||
Address = %s
|
Address = %s
|
||||||
PrivateKey = %s
|
PrivateKey = %s
|
||||||
|
MTU = %d
|
||||||
%s
|
%s
|
||||||
|
|
||||||
[Peer]
|
[Peer]
|
||||||
|
@ -164,6 +170,7 @@ Endpoint = %s
|
||||||
|
|
||||||
`, client.Address+"/32",
|
`, client.Address+"/32",
|
||||||
client.PrivateKey,
|
client.PrivateKey,
|
||||||
|
defaultMTU,
|
||||||
defaultDNS,
|
defaultDNS,
|
||||||
gwnode.PublicKey,
|
gwnode.PublicKey,
|
||||||
newAllowedIPs,
|
newAllowedIPs,
|
||||||
|
@ -228,6 +235,8 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
extclient.IngressGatewayEndpoint = node.Endpoint + ":" + strconv.FormatInt(int64(node.ListenPort), 10)
|
extclient.IngressGatewayEndpoint = node.Endpoint + ":" + strconv.FormatInt(int64(node.ListenPort), 10)
|
||||||
|
// TODO, could rely on network template as well in future
|
||||||
|
extclient.Enabled = true
|
||||||
err = json.NewDecoder(r.Body).Decode(&extclient)
|
err = json.NewDecoder(r.Body).Decode(&extclient)
|
||||||
if err != nil && !errors.Is(err, io.EOF) {
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
@ -238,6 +247,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger.Log(0, r.Header.Get("user"), "created new ext client on network", networkName)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
err = mq.PublishExtPeerUpdate(&node)
|
err = mq.PublishExtPeerUpdate(&node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -268,12 +278,20 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newclient, err := logic.UpdateExtClient(newExtClient.ClientID, params["network"], &oldExtClient)
|
var changedEnabled = newExtClient.Enabled != oldExtClient.Enabled // indicates there was a change in enablement
|
||||||
|
newclient, err := logic.UpdateExtClient(newExtClient.ClientID, params["network"], newExtClient.Enabled, &oldExtClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Log(1, r.Header.Get("user"), "updated client", newExtClient.ClientID)
|
logger.Log(0, r.Header.Get("user"), "updated ext client", newExtClient.ClientID)
|
||||||
|
if changedEnabled { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
|
||||||
|
if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil {
|
||||||
|
if err = mq.PublishExtPeerUpdate(&ingressNode); err != nil {
|
||||||
|
logger.Log(1, "error setting ext peers on", ingressNode.ID, ":", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(newclient)
|
json.NewEncoder(w).Encode(newclient)
|
||||||
}
|
}
|
||||||
|
@ -311,7 +329,7 @@ func deleteExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(1, "error setting ext peers on "+ingressnode.ID+": "+err.Error())
|
logger.Log(1, "error setting ext peers on "+ingressnode.ID+": "+err.Error())
|
||||||
}
|
}
|
||||||
logger.Log(1, r.Header.Get("user"),
|
logger.Log(0, r.Header.Get("user"),
|
||||||
"Deleted extclient client", params["clientid"], "from network", params["network"])
|
"Deleted extclient client", params["clientid"], "from network", params["network"])
|
||||||
returnSuccessResponse(w, r, params["clientid"]+" deleted.")
|
returnSuccessResponse(w, r, params["clientid"]+" deleted.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/mq"
|
"github.com/gravitl/netmaker/mq"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
@ -34,6 +35,9 @@ func networkHandlers(r *mux.Router) {
|
||||||
r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
|
r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
|
||||||
r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
|
r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
|
||||||
r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
|
r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
|
||||||
|
// ACLs
|
||||||
|
r.HandleFunc("/api/networks/{networkname}/acls", securityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods("PUT")
|
||||||
|
r.HandleFunc("/api/networks/{networkname}/acls", securityCheck(true, http.HandlerFunc(getNetworkACL))).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
//simple get all networks function
|
//simple get all networks function
|
||||||
|
@ -231,6 +235,58 @@ func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
|
||||||
json.NewEncoder(w).Encode(network)
|
json.NewEncoder(w).Encode(network)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
netname := params["networkname"]
|
||||||
|
var networkACLChange acls.ACLContainer
|
||||||
|
networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = json.NewDecoder(r.Body).Decode(&networkACLChange)
|
||||||
|
newNetACL, err := networkACLChange.Save(acls.ContainerID(netname))
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
|
||||||
|
|
||||||
|
// send peer updates
|
||||||
|
if servercfg.IsMessageQueueBackend() {
|
||||||
|
serverNode, err := logic.GetNetworkServerLocal(netname)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "failed to find server node after ACL update on", netname)
|
||||||
|
} else {
|
||||||
|
if err = logic.ServerUpdate(&serverNode, false); err != nil {
|
||||||
|
logger.Log(1, "failed to update server node after ACL update on", netname)
|
||||||
|
}
|
||||||
|
if err = mq.PublishPeerUpdate(&serverNode); err != nil {
|
||||||
|
logger.Log(0, "failed to publish peer update after ACL update on", netname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(newNetACL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetworkACL(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
netname := params["networkname"]
|
||||||
|
var networkACL acls.ACLContainer
|
||||||
|
networkACL, err := networkACL.Get(acls.ContainerID(netname))
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Log(2, r.Header.Get("user"), "fetched acl for network", netname)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(networkACL)
|
||||||
|
}
|
||||||
|
|
||||||
// Delete a network
|
// Delete a network
|
||||||
// Will stop you if there's any nodes associated
|
// Will stop you if there's any nodes associated
|
||||||
func deleteNetwork(w http.ResponseWriter, r *http.Request) {
|
func deleteNetwork(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -34,7 +34,6 @@ func nodeHandlers(r *mux.Router) {
|
||||||
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
||||||
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
|
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func authenticate(response http.ResponseWriter, request *http.Request) {
|
func authenticate(response http.ResponseWriter, request *http.Request) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -143,6 +145,72 @@ func TestValidateEgressGateway(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNodeACLs(t *testing.T) {
|
||||||
|
deleteAllNodes()
|
||||||
|
node1 := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", Endpoint: "10.0.0.50", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet", OS: "linux"}
|
||||||
|
node2 := models.Node{PublicKey: "DM5qhLAE20FG7BbfBCger+Ac9D2NDOwCtY1rbYDXf14=", Name: "testnode", Endpoint: "10.0.0.100", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet", OS: "linux"}
|
||||||
|
logic.CreateNode(&node1)
|
||||||
|
logic.CreateNode(&node2)
|
||||||
|
t.Run("acls not present", func(t *testing.T) {
|
||||||
|
currentACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(node1.Network))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, currentACL)
|
||||||
|
node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, node1ACL)
|
||||||
|
assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
|
||||||
|
})
|
||||||
|
t.Run("node acls exists after creates", func(t *testing.T) {
|
||||||
|
node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, node1ACL)
|
||||||
|
node2ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node2.Network), nodeacls.NodeID(node2.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, node2ACL)
|
||||||
|
assert.Equal(t, acls.Allowed, node2ACL[acls.AclID(node1.ID)])
|
||||||
|
})
|
||||||
|
t.Run("node acls correct after fetch", func(t *testing.T) {
|
||||||
|
node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
|
||||||
|
})
|
||||||
|
t.Run("node acls correct after modify", func(t *testing.T) {
|
||||||
|
node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, node1ACL)
|
||||||
|
node2ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node2.Network), nodeacls.NodeID(node2.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, node2ACL)
|
||||||
|
currentACL, err := nodeacls.DisallowNodes(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), nodeacls.NodeID(node2.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, acls.NotAllowed, currentACL[acls.AclID(node1.ID)][acls.AclID(node2.ID)])
|
||||||
|
assert.Equal(t, acls.NotAllowed, currentACL[acls.AclID(node2.ID)][acls.AclID(node1.ID)])
|
||||||
|
currentACL.Save(acls.ContainerID(node1.Network))
|
||||||
|
})
|
||||||
|
t.Run("node acls correct after add new node not allowed", func(t *testing.T) {
|
||||||
|
node3 := models.Node{PublicKey: "DM5qhLAE20FG7BbfBCger+Ac9D2NDOwCtY1rbYDXv24=", Name: "testnode3", Endpoint: "10.0.0.100", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet", OS: "linux"}
|
||||||
|
logic.CreateNode(&node3)
|
||||||
|
var currentACL, err = nodeacls.FetchAllACLs(nodeacls.NetworkID(node3.Network))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, currentACL)
|
||||||
|
assert.Equal(t, acls.NotPresent, currentACL[acls.AclID(node1.ID)][acls.AclID(node3.ID)])
|
||||||
|
nodeACL, err := nodeacls.CreateNodeACL(nodeacls.NetworkID(node3.Network), nodeacls.NodeID(node3.ID), acls.NotAllowed)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
nodeACL.Save(acls.ContainerID(node3.Network), acls.AclID(node3.ID))
|
||||||
|
currentACL, err = nodeacls.FetchAllACLs(nodeacls.NetworkID(node3.Network))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, acls.NotAllowed, currentACL[acls.AclID(node1.ID)][acls.AclID(node3.ID)])
|
||||||
|
assert.Equal(t, acls.NotAllowed, currentACL[acls.AclID(node2.ID)][acls.AclID(node3.ID)])
|
||||||
|
})
|
||||||
|
t.Run("node acls removed", func(t *testing.T) {
|
||||||
|
retNetworkACL, err := nodeacls.RemoveNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, retNetworkACL)
|
||||||
|
assert.Equal(t, acls.NotPresent, retNetworkACL[acls.AclID(node2.ID)][acls.AclID(node1.ID)])
|
||||||
|
})
|
||||||
|
deleteAllNodes()
|
||||||
|
}
|
||||||
|
|
||||||
func deleteAllNodes() {
|
func deleteAllNodes() {
|
||||||
database.DeleteAllRecords(database.NODES_TABLE_NAME)
|
database.DeleteAllRecords(database.NODES_TABLE_NAME)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ const DATABASE_FILENAME = "netmaker.db"
|
||||||
// GENERATED_TABLE_NAME - stores server generated k/v
|
// GENERATED_TABLE_NAME - stores server generated k/v
|
||||||
const GENERATED_TABLE_NAME = "generated"
|
const GENERATED_TABLE_NAME = "generated"
|
||||||
|
|
||||||
|
// NODE_ACLS_TABLE_NAME - stores the node ACL rules
|
||||||
|
const NODE_ACLS_TABLE_NAME = "nodeacls"
|
||||||
|
|
||||||
// == ERROR CONSTS ==
|
// == ERROR CONSTS ==
|
||||||
|
|
||||||
// NO_RECORD - no singular result found
|
// NO_RECORD - no singular result found
|
||||||
|
@ -127,6 +130,7 @@ func createTables() {
|
||||||
createTable(SERVERCONF_TABLE_NAME)
|
createTable(SERVERCONF_TABLE_NAME)
|
||||||
createTable(SERVER_UUID_TABLE_NAME)
|
createTable(SERVER_UUID_TABLE_NAME)
|
||||||
createTable(GENERATED_TABLE_NAME)
|
createTable(GENERATED_TABLE_NAME)
|
||||||
|
createTable(NODE_ACLS_TABLE_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTable(tableName string) error {
|
func createTable(tableName string) error {
|
||||||
|
|
10
go.mod
10
go.mod
|
@ -4,7 +4,7 @@ go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||||
github.com/go-playground/validator/v10 v10.10.0
|
github.com/go-playground/validator/v10 v10.10.1
|
||||||
github.com/golang-jwt/jwt/v4 v4.3.0
|
github.com/golang-jwt/jwt/v4 v4.3.0
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
|
@ -17,15 +17,15 @@ require (
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/txn2/txeh v1.3.0
|
github.com/txn2/txeh v1.3.0
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect
|
||||||
golang.org/x/text v0.3.7-0.20210524175448-3115f89c4b99 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20210805125648-3957e9b9dd19 // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20210805125648-3957e9b9dd19 // indirect
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de
|
||||||
google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
|
google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
|
||||||
google.golang.org/grpc v1.44.0
|
google.golang.org/grpc v1.45.0
|
||||||
google.golang.org/protobuf v1.27.1
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/ini.v1 v1.66.4
|
gopkg.in/ini.v1 v1.66.4
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
|
|
20
go.sum
20
go.sum
|
@ -69,8 +69,8 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb
|
||||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
|
github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig=
|
||||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
@ -275,8 +275,8 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
@ -304,8 +304,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -355,8 +355,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7-0.20210524175448-3115f89c4b99 h1:ZEXtoJu1S0ie/EmdYnjY3CqaCCZxnldL+K1ftMITD2Q=
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
golang.org/x/text v0.3.7-0.20210524175448-3115f89c4b99/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -389,8 +389,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
|
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|
124
logic/acls/common.go
Normal file
124
logic/acls/common.go
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package acls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
// == type functions ==
|
||||||
|
|
||||||
|
// ACL.Allow - allows access by ID in memory
|
||||||
|
func (acl ACL) Allow(ID AclID) {
|
||||||
|
acl[ID] = Allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACL.DisallowNode - disallows access by ID in memory
|
||||||
|
func (acl ACL) Disallow(ID AclID) {
|
||||||
|
acl[ID] = NotAllowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACL.Remove - removes a node from a ACL in memory
|
||||||
|
func (acl ACL) Remove(ID AclID) {
|
||||||
|
delete(acl, ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACL.Update - updates a ACL in DB
|
||||||
|
func (acl ACL) Save(containerID ContainerID, ID AclID) (ACL, error) {
|
||||||
|
return upsertACL(containerID, ID, acl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACL.IsAllowed - sees if ID is allowed in referring ACL
|
||||||
|
func (acl ACL) IsAllowed(ID AclID) bool {
|
||||||
|
return acl[ID] == Allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.IsAllowed - returns if the current ACL container contains allowed ACLs between two IDs
|
||||||
|
func (aclContainer ACLContainer) IsAllowed(ID1, ID2 AclID) bool {
|
||||||
|
return aclContainer[ID1].IsAllowed(ID2) && aclContainer[ID2].IsAllowed(ID1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.UpdateACL - saves the state of a ACL in the ACLContainer in memory
|
||||||
|
func (aclContainer ACLContainer) UpdateACL(ID AclID, acl ACL) ACLContainer {
|
||||||
|
aclContainer[ID] = acl
|
||||||
|
return aclContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.RemoveACL - removes the state of a ACL in the ACLContainer in memory
|
||||||
|
func (aclContainer ACLContainer) RemoveACL(ID AclID) ACLContainer {
|
||||||
|
delete(aclContainer, ID)
|
||||||
|
return aclContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.ChangeAccess - changes the relationship between two nodes in memory
|
||||||
|
func (networkACL ACLContainer) ChangeAccess(ID1, ID2 AclID, value byte) {
|
||||||
|
networkACL[ID1][ID2] = value
|
||||||
|
networkACL[ID2][ID1] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.Save - saves the state of a ACLContainer to the db
|
||||||
|
func (aclContainer ACLContainer) Save(containerID ContainerID) (ACLContainer, error) {
|
||||||
|
return upsertACLContainer(containerID, aclContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.New - saves the state of a ACLContainer to the db
|
||||||
|
func (aclContainer ACLContainer) New(containerID ContainerID) (ACLContainer, error) {
|
||||||
|
return upsertACLContainer(containerID, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLContainer.Get - saves the state of a ACLContainer to the db
|
||||||
|
func (aclContainer ACLContainer) Get(containerID ContainerID) (ACLContainer, error) {
|
||||||
|
return fetchACLContainer(containerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// == private ==
|
||||||
|
|
||||||
|
// fetchACLContainer - fetches all current rules in given ACL container
|
||||||
|
func fetchACLContainer(containerID ContainerID) (ACLContainer, error) {
|
||||||
|
aclJson, err := fetchACLContainerJson(ContainerID(containerID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var currentNetworkACL ACLContainer
|
||||||
|
if err := json.Unmarshal([]byte(aclJson), ¤tNetworkACL); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return currentNetworkACL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchACLContainerJson - fetch the current ACL of given container except in json string
|
||||||
|
func fetchACLContainerJson(containerID ContainerID) (ACLJson, error) {
|
||||||
|
currentACLs, err := database.FetchRecord(database.NODE_ACLS_TABLE_NAME, string(containerID))
|
||||||
|
if err != nil {
|
||||||
|
return ACLJson(""), err
|
||||||
|
}
|
||||||
|
return ACLJson(currentACLs), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// upsertACL - applies a ACL to the db, overwrites or creates
|
||||||
|
func upsertACL(containerID ContainerID, ID AclID, acl ACL) (ACL, error) {
|
||||||
|
currentNetACL, err := fetchACLContainer(containerID)
|
||||||
|
if err != nil {
|
||||||
|
return acl, err
|
||||||
|
}
|
||||||
|
currentNetACL[ID] = acl
|
||||||
|
_, err = upsertACLContainer(containerID, currentNetACL)
|
||||||
|
return acl, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// upsertACLContainer - Inserts or updates a network ACL given the json string of the ACL and the container ID
|
||||||
|
// if nil, create it
|
||||||
|
func upsertACLContainer(containerID ContainerID, aclContainer ACLContainer) (ACLContainer, error) {
|
||||||
|
if aclContainer == nil {
|
||||||
|
aclContainer = make(ACLContainer)
|
||||||
|
}
|
||||||
|
return aclContainer, database.Insert(string(containerID), string(convertNetworkACLtoACLJson(aclContainer)), database.NODE_ACLS_TABLE_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertNetworkACLtoACLJson(networkACL ACLContainer) ACLJson {
|
||||||
|
data, err := json.Marshal(networkACL)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ACLJson(data)
|
||||||
|
}
|
87
logic/acls/nodeacls/modify.go
Normal file
87
logic/acls/nodeacls/modify.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package nodeacls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateNodeACL - inserts or updates a node ACL on given network and adds to state
|
||||||
|
func CreateNodeACL(networkID NetworkID, nodeID NodeID, defaultVal byte) (acls.ACL, error) {
|
||||||
|
if defaultVal != acls.NotAllowed && defaultVal != acls.Allowed {
|
||||||
|
defaultVal = acls.NotAllowed
|
||||||
|
}
|
||||||
|
var currentNetworkACL, err = FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
if database.IsEmptyRecord(err) {
|
||||||
|
currentNetworkACL, err = currentNetworkACL.New(acls.ContainerID(networkID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var newNodeACL = make(acls.ACL)
|
||||||
|
for existingNodeID := range currentNetworkACL {
|
||||||
|
currentNetworkACL[existingNodeID][acls.AclID(nodeID)] = defaultVal // set the old nodes to default value for new node
|
||||||
|
newNodeACL[existingNodeID] = defaultVal // set the old nodes in new node ACL to default value
|
||||||
|
}
|
||||||
|
currentNetworkACL[acls.AclID(nodeID)] = newNodeACL // append the new node's ACL
|
||||||
|
retNetworkACL, err := currentNetworkACL.Save(acls.ContainerID(networkID)) // insert into db
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return retNetworkACL[acls.AclID(nodeID)], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowNode - allow access between two nodes in memory
|
||||||
|
func AllowNodes(networkID NetworkID, node1, node2 NodeID) (acls.ACLContainer, error) {
|
||||||
|
container, err := FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
container[acls.AclID(node1)].Allow(acls.AclID(node2))
|
||||||
|
container[acls.AclID(node2)].Allow(acls.AclID(node1))
|
||||||
|
return container, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisallowNodes - deny access between two nodes
|
||||||
|
func DisallowNodes(networkID NetworkID, node1, node2 NodeID) (acls.ACLContainer, error) {
|
||||||
|
container, err := FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
container[acls.AclID(node1)].Disallow(acls.AclID(node2))
|
||||||
|
container[acls.AclID(node2)].Disallow(acls.AclID(node1))
|
||||||
|
return container, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNodeACL - updates a node's ACL in state
|
||||||
|
func UpdateNodeACL(networkID NetworkID, nodeID NodeID, acl acls.ACL) (acls.ACL, error) {
|
||||||
|
var currentNetworkACL, err = FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
currentNetworkACL[acls.AclID(nodeID)] = acl
|
||||||
|
return currentNetworkACL[acls.AclID(nodeID)].Save(acls.ContainerID(networkID), acls.AclID(nodeID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveNodeACL - removes a specific Node's ACL, returns the NetworkACL and error
|
||||||
|
func RemoveNodeACL(networkID NetworkID, nodeID NodeID) (acls.ACLContainer, error) {
|
||||||
|
var currentNetworkACL, err = FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for currentNodeID := range currentNetworkACL {
|
||||||
|
if NodeID(currentNodeID) != nodeID {
|
||||||
|
currentNetworkACL[currentNodeID].Remove(acls.AclID(nodeID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(currentNetworkACL, acls.AclID(nodeID))
|
||||||
|
return currentNetworkACL.Save(acls.ContainerID(networkID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteACLContainer - removes an ACLContainer state from db
|
||||||
|
func DeleteACLContainer(network NetworkID) error {
|
||||||
|
return database.DeleteRecord(database.NODE_ACLS_TABLE_NAME, string(network))
|
||||||
|
}
|
53
logic/acls/nodeacls/retrieve.go
Normal file
53
logic/acls/nodeacls/retrieve.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package nodeacls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AreNodesAllowed - checks if nodes are allowed to communicate in their network ACL
|
||||||
|
func AreNodesAllowed(networkID NetworkID, node1, node2 NodeID) bool {
|
||||||
|
var currentNetworkACL, err = FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return currentNetworkACL[acls.AclID(node1)].IsAllowed(acls.AclID(node2)) && currentNetworkACL[acls.AclID(node2)].IsAllowed(acls.AclID(node1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchNodeACL - fetches a specific node's ACL in a given network
|
||||||
|
func FetchNodeACL(networkID NetworkID, nodeID NodeID) (acls.ACL, error) {
|
||||||
|
var currentNetworkACL, err = FetchAllACLs(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if currentNetworkACL[acls.AclID(nodeID)] == nil {
|
||||||
|
return nil, fmt.Errorf("no node ACL present for node %s", nodeID)
|
||||||
|
}
|
||||||
|
return currentNetworkACL[acls.AclID(nodeID)], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchNodeACLJson - fetches a node's acl in given network except returns the json string
|
||||||
|
func FetchNodeACLJson(networkID NetworkID, nodeID NodeID) (acls.ACLJson, error) {
|
||||||
|
currentNodeACL, err := FetchNodeACL(networkID, nodeID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
jsonData, err := json.Marshal(¤tNodeACL)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return acls.ACLJson(jsonData), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchAllACLs - fetchs all node
|
||||||
|
func FetchAllACLs(networkID NetworkID) (acls.ACLContainer, error) {
|
||||||
|
var err error
|
||||||
|
var currentNetworkACL acls.ACLContainer
|
||||||
|
currentNetworkACL, err = currentNetworkACL.Get(acls.ContainerID(networkID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return currentNetworkACL, nil
|
||||||
|
}
|
14
logic/acls/nodeacls/types.go
Normal file
14
logic/acls/nodeacls/types.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package nodeacls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// NodeACL - interface for NodeACLs
|
||||||
|
NodeACL acls.ACL
|
||||||
|
// NodeID - node ID for ACLs
|
||||||
|
NodeID acls.AclID
|
||||||
|
// NetworkID - ACL container based on network ID for nodes
|
||||||
|
NetworkID acls.ContainerID
|
||||||
|
)
|
27
logic/acls/types.go
Normal file
27
logic/acls/types.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package acls
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NotPresent - 0 - not present (default)
|
||||||
|
NotPresent = byte(0)
|
||||||
|
// NotAllowed - 1 - not allowed access
|
||||||
|
NotAllowed = byte(1) // 1 - not allowed
|
||||||
|
// Allowed - 2 - allowed access
|
||||||
|
Allowed = byte(2)
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// AclID - the node id of a given node
|
||||||
|
AclID string
|
||||||
|
|
||||||
|
// ACL - the ACL of other nodes in a NetworkACL for a single unique node
|
||||||
|
ACL map[AclID]byte
|
||||||
|
|
||||||
|
// ACLJson - the string representation in JSON of an ACL Node or Network
|
||||||
|
ACLJson string
|
||||||
|
|
||||||
|
// ContainerID - the networkID of a given network
|
||||||
|
ContainerID string
|
||||||
|
|
||||||
|
// ACLContainer - the total list of all node's ACL in a given network
|
||||||
|
ACLContainer map[AclID]ACL
|
||||||
|
)
|
|
@ -33,7 +33,7 @@ func GetExtPeersList(node *models.Node) ([]models.ExtPeersResponse, error) {
|
||||||
logger.Log(2, "failed to unmarshal ext client")
|
logger.Log(2, "failed to unmarshal ext client")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if extClient.Network == node.Network && extClient.IngressGatewayID == node.ID {
|
if extClient.Enabled && extClient.Network == node.Network && extClient.IngressGatewayID == node.ID {
|
||||||
peers = append(peers, peer)
|
peers = append(peers, peer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,14 @@ func CreateExtClient(extclient *models.ExtClient) error {
|
||||||
extclient.Address = newAddress
|
extclient.Address = newAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if extclient.Address6 == "" {
|
||||||
|
addr6, err := UniqueAddress6(extclient.Network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
extclient.Address6 = addr6
|
||||||
|
}
|
||||||
|
|
||||||
if extclient.ClientID == "" {
|
if extclient.ClientID == "" {
|
||||||
extclient.ClientID = models.GenerateNodeName()
|
extclient.ClientID = models.GenerateNodeName()
|
||||||
}
|
}
|
||||||
|
@ -150,18 +158,18 @@ func CreateExtClient(extclient *models.ExtClient) error {
|
||||||
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = SetNetworkNodesLastModified(extclient.Network)
|
return SetNetworkNodesLastModified(extclient.Network)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateExtClient - only supports name changes right now
|
// UpdateExtClient - only supports name changes right now
|
||||||
func UpdateExtClient(newclientid string, network string, client *models.ExtClient) (*models.ExtClient, error) {
|
func UpdateExtClient(newclientid string, network string, enabled bool, client *models.ExtClient) (*models.ExtClient, error) {
|
||||||
|
|
||||||
err := DeleteExtClient(network, client.ClientID)
|
err := DeleteExtClient(network, client.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return client, err
|
return client, err
|
||||||
}
|
}
|
||||||
client.ClientID = newclientid
|
client.ClientID = newclientid
|
||||||
|
client.Enabled = enabled
|
||||||
CreateExtClient(client)
|
CreateExtClient(client)
|
||||||
return client, err
|
return client, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/validation"
|
"github.com/gravitl/netmaker/validation"
|
||||||
|
@ -41,6 +42,11 @@ func GetNetworks() ([]models.Network, error) {
|
||||||
|
|
||||||
// DeleteNetwork - deletes a network
|
// DeleteNetwork - deletes a network
|
||||||
func DeleteNetwork(network string) error {
|
func DeleteNetwork(network string) error {
|
||||||
|
// remove ACL for network
|
||||||
|
err := nodeacls.DeleteACLContainer(nodeacls.NetworkID(network))
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "failed to remove the node acls during network delete for network,", network)
|
||||||
|
}
|
||||||
nodeCount, err := GetNetworkNonServerNodeCount(network)
|
nodeCount, err := GetNetworkNonServerNodeCount(network)
|
||||||
if nodeCount == 0 || database.IsEmptyRecord(err) {
|
if nodeCount == 0 || database.IsEmptyRecord(err) {
|
||||||
// delete server nodes first then db records
|
// delete server nodes first then db records
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
@ -174,6 +176,41 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
|
||||||
return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.")
|
return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteNodeByID - deletes a node from database or moves into delete nodes table
|
||||||
|
func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
||||||
|
var err error
|
||||||
|
var key = node.ID
|
||||||
|
if !exterminate {
|
||||||
|
node.Action = models.NODE_DELETE
|
||||||
|
nodedata, err := json.Marshal(&node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
|
||||||
|
logger.Log(2, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if servercfg.IsDNSMode() {
|
||||||
|
SetDNS()
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = nodeacls.RemoveNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID))
|
||||||
|
if err != nil {
|
||||||
|
// ignoring for now, could hit a nil pointer if delete called twice
|
||||||
|
logger.Log(2, "attempted to remove node ACL for node", node.Name, node.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return removeLocalServer(node)
|
||||||
|
}
|
||||||
|
|
||||||
// IsNodeIDUnique - checks if node id is unique
|
// IsNodeIDUnique - checks if node id is unique
|
||||||
func IsNodeIDUnique(node *models.Node) (bool, error) {
|
func IsNodeIDUnique(node *models.Node) (bool, error) {
|
||||||
_, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
|
_, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
|
||||||
|
@ -274,6 +311,13 @@ func CreateNode(node *models.Node) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// TODO get template logic to decide initial ACL value
|
||||||
|
_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), acls.Allowed)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "failed to create node ACL for node,", node.ID, "err:", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if node.IsPending != "yes" {
|
if node.IsPending != "yes" {
|
||||||
DecrimentKey(node.Network, node.AccessKey)
|
DecrimentKey(node.Network, node.AccessKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
package logic
|
package logic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
@ -33,7 +35,7 @@ func GetHubPeer(networkName string) []models.Node {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GetNodePeers - fetches peers for a given node
|
// GetNodePeers - fetches peers for a given node
|
||||||
func GetNodePeers(networkName string, excludeRelayed bool, isP2S bool) ([]models.Node, error) {
|
func GetNodePeers(networkName, nodeid string, excludeRelayed bool, isP2S bool) ([]models.Node, error) {
|
||||||
var peers []models.Node
|
var peers []models.Node
|
||||||
var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName)
|
var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,7 +47,16 @@ func GetNodePeers(networkName string, excludeRelayed bool, isP2S bool) ([]models
|
||||||
logger.Log(2, errN.Error())
|
logger.Log(2, errN.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentNetworkACLs, aclErr := nodeacls.FetchAllACLs(nodeacls.NetworkID(networkName))
|
||||||
|
if aclErr != nil {
|
||||||
|
return peers, aclErr
|
||||||
|
}
|
||||||
|
|
||||||
for _, node := range networkNodes {
|
for _, node := range networkNodes {
|
||||||
|
if !currentNetworkACLs.IsAllowed(acls.AclID(nodeid), acls.AclID(node.ID)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var peer = models.Node{}
|
var peer = models.Node{}
|
||||||
if node.IsEgressGateway == "yes" { // handle egress stuff
|
if node.IsEgressGateway == "yes" { // handle egress stuff
|
||||||
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
||||||
|
@ -79,7 +90,7 @@ func GetNodePeers(networkName string, excludeRelayed bool, isP2S bool) ([]models
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isP2S || peer.IsHub == "yes" {
|
if (!isP2S || peer.IsHub == "yes") && currentNetworkACLs.IsAllowed(acls.AclID(nodeid), acls.AclID(node.ID)) {
|
||||||
peers = append(peers, peer)
|
peers = append(peers, peer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +118,7 @@ func GetPeersList(refnode *models.Node) ([]models.Node, error) {
|
||||||
isP2S = true
|
isP2S = true
|
||||||
}
|
}
|
||||||
if relayedNodeAddr == "" {
|
if relayedNodeAddr == "" {
|
||||||
peers, err = GetNodePeers(networkName, excludeRelayed, isP2S)
|
peers, err = GetNodePeers(networkName, refnode.ID, excludeRelayed, isP2S)
|
||||||
} else {
|
} else {
|
||||||
var relayNode models.Node
|
var relayNode models.Node
|
||||||
relayNode, err = GetNodeRelay(networkName, relayedNodeAddr)
|
relayNode, err = GetNodeRelay(networkName, relayedNodeAddr)
|
||||||
|
@ -127,7 +138,7 @@ func GetPeersList(refnode *models.Node) ([]models.Node, error) {
|
||||||
} else {
|
} else {
|
||||||
peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...)
|
peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...)
|
||||||
}
|
}
|
||||||
nodepeers, err := GetNodePeers(networkName, false, isP2S)
|
nodepeers, err := GetNodePeers(networkName, refnode.ID, false, isP2S)
|
||||||
if err == nil && peerNode.UDPHolePunch == "yes" {
|
if err == nil && peerNode.UDPHolePunch == "yes" {
|
||||||
for _, nodepeer := range nodepeers {
|
for _, nodepeer := range nodepeers {
|
||||||
if nodepeer.Address == peerNode.Address {
|
if nodepeer.Address == peerNode.Address {
|
||||||
|
@ -165,11 +176,13 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
|
||||||
// #1 Set Keepalive values: set_keepalive
|
// #1 Set Keepalive values: set_keepalive
|
||||||
// #2 Set local address: set_local - could be a LOT BETTER and fix some bugs with additional logic
|
// #2 Set local address: set_local - could be a LOT BETTER and fix some bugs with additional logic
|
||||||
// #3 Set allowedips: set_allowedips
|
// #3 Set allowedips: set_allowedips
|
||||||
|
var dns string
|
||||||
for _, peer := range currentPeers {
|
for _, peer := range currentPeers {
|
||||||
if peer.ID == node.ID {
|
if peer.ID == node.ID {
|
||||||
//skip yourself
|
//skip yourself
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
dns = dns + fmt.Sprintf("%s %s.%s\n", peer.Address, peer.Name, peer.Network)
|
||||||
pubkey, err := wgtypes.ParseKey(peer.PublicKey)
|
pubkey, err := wgtypes.ParseKey(peer.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.PeerUpdate{}, err
|
return models.PeerUpdate{}, err
|
||||||
|
@ -225,12 +238,7 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
dns, err := os.ReadFile("./config/dnsconfig/netmaker.hosts")
|
peerUpdate.DNS = dns
|
||||||
if err != nil {
|
|
||||||
logger.Log(0, "failed to read netmaker.hosts", err.Error())
|
|
||||||
} else {
|
|
||||||
peerUpdate.DNS = dns
|
|
||||||
}
|
|
||||||
return peerUpdate, nil
|
return peerUpdate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
@ -208,6 +210,11 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
||||||
return nil, hasGateway, gateways, err
|
return nil, hasGateway, gateways, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentNetworkACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(serverNode.Network))
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(1, "could not fetch current ACL list, proceeding with all peers")
|
||||||
|
}
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
pubkey, err := wgtypes.ParseKey(node.PublicKey)
|
pubkey, err := wgtypes.ParseKey(node.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -225,6 +232,9 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if currentNetworkACL != nil && currentNetworkACL.IsAllowed(acls.AclID(serverNode.ID), acls.AclID(node.ID)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var peer wgtypes.PeerConfig
|
var peer wgtypes.PeerConfig
|
||||||
var peeraddr = net.IPNet{
|
var peeraddr = net.IPNet{
|
||||||
|
@ -290,6 +300,7 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
||||||
ReplaceAllowedIPs: true,
|
ReplaceAllowedIPs: true,
|
||||||
AllowedIPs: allowedips,
|
AllowedIPs: allowedips,
|
||||||
}
|
}
|
||||||
|
|
||||||
peers = append(peers, peer)
|
peers = append(peers, peer)
|
||||||
}
|
}
|
||||||
if serverNode.IsIngressGateway == "yes" {
|
if serverNode.IsIngressGateway == "yes" {
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsBase64 - checks if a string is in base64 format
|
// IsBase64 - checks if a string is in base64 format
|
||||||
|
@ -101,34 +100,6 @@ func GenerateCryptoString(n int) (string, error) {
|
||||||
return string(ret), nil
|
return string(ret), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteNodeByID - deletes a node from database or moves into delete nodes table
|
|
||||||
func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
|
||||||
var err error
|
|
||||||
var key = node.ID
|
|
||||||
if !exterminate {
|
|
||||||
node.Action = models.NODE_DELETE
|
|
||||||
nodedata, err := json.Marshal(&node)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
|
|
||||||
logger.Log(2, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if servercfg.IsDNSMode() {
|
|
||||||
SetDNS()
|
|
||||||
}
|
|
||||||
return removeLocalServer(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomString - returns a random string in a charset
|
// RandomString - returns a random string in a charset
|
||||||
func RandomString(length int) string {
|
func RandomString(length int) string {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
@ -181,6 +152,7 @@ func setPeerInfo(node *models.Node) models.Node {
|
||||||
peer.PublicKey = node.PublicKey
|
peer.PublicKey = node.PublicKey
|
||||||
peer.Endpoint = node.Endpoint
|
peer.Endpoint = node.Endpoint
|
||||||
peer.Name = node.Name
|
peer.Name = node.Name
|
||||||
|
peer.Network = node.Network
|
||||||
peer.LocalAddress = node.LocalAddress
|
peer.LocalAddress = node.LocalAddress
|
||||||
peer.ListenPort = node.ListenPort
|
peer.ListenPort = node.ListenPort
|
||||||
peer.AllowedIPs = node.AllowedIPs
|
peer.AllowedIPs = node.AllowedIPs
|
||||||
|
|
5
main.go
5
main.go
|
@ -66,6 +66,11 @@ func initialize() { // Client Mode Prereq Check
|
||||||
logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
|
logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = serverctl.SetDefaultACLS()
|
||||||
|
if err != nil {
|
||||||
|
logger.FatalLog("error setting default acls: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
if servercfg.IsClientMode() != "off" {
|
if servercfg.IsClientMode() != "off" {
|
||||||
output, err := ncutils.RunCmd("id -u", true)
|
output, err := ncutils.RunCmd("id -u", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,7 +8,9 @@ type ExtClient struct {
|
||||||
PublicKey string `json:"publickey" bson:"publickey"`
|
PublicKey string `json:"publickey" bson:"publickey"`
|
||||||
Network string `json:"network" bson:"network"`
|
Network string `json:"network" bson:"network"`
|
||||||
Address string `json:"address" bson:"address"`
|
Address string `json:"address" bson:"address"`
|
||||||
|
Address6 string `json:"address6" bson:"address6"`
|
||||||
IngressGatewayID string `json:"ingressgatewayid" bson:"ingressgatewayid"`
|
IngressGatewayID string `json:"ingressgatewayid" bson:"ingressgatewayid"`
|
||||||
IngressGatewayEndpoint string `json:"ingressgatewayendpoint" bson:"ingressgatewayendpoint"`
|
IngressGatewayEndpoint string `json:"ingressgatewayendpoint" bson:"ingressgatewayendpoint"`
|
||||||
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
||||||
|
Enabled bool `json:"enabled" bson:"enabled"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ type PeerUpdate struct {
|
||||||
Network string `json:"network" bson:"network" yaml:"network"`
|
Network string `json:"network" bson:"network" yaml:"network"`
|
||||||
ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
|
ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
|
||||||
Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
|
Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
|
||||||
DNS []byte `json:"dns" bson:'dns" yaml:"dns"`
|
DNS string `json:"dns" bson:"dns" yaml:"dns"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyUpdate - key update struct
|
// KeyUpdate - key update struct
|
||||||
|
|
15
netclient/build/netclient.service
Normal file
15
netclient/build/netclient.service
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Netclient Daemon
|
||||||
|
Documentation=https://docs.netmaker.org https://k8s.netmaker.org
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target systemd-networkd-wait-online.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=root
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/sbin/netclient daemon
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=15s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -3,13 +3,11 @@ package functions
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
"github.com/gravitl/netmaker/logger"
|
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
"github.com/gravitl/netmaker/netclient/local"
|
"github.com/gravitl/netmaker/netclient/local"
|
||||||
|
@ -143,7 +141,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
|
||||||
//deal with DNS
|
//deal with DNS
|
||||||
if newNode.DNSOn != "yes" && shouldDNSChange && nodeCfg.Node.Interface != "" {
|
if newNode.DNSOn != "yes" && shouldDNSChange && nodeCfg.Node.Interface != "" {
|
||||||
ncutils.Log("settng DNS off")
|
ncutils.Log("settng DNS off")
|
||||||
if err := removeHostDNS(ncutils.IsWindows()); err != nil {
|
if err := removeHostDNS(nodeCfg.Network, ncutils.IsWindows()); err != nil {
|
||||||
ncutils.Log("error removing netmaker profile from /etc/hosts " + err.Error())
|
ncutils.Log("error removing netmaker profile from /etc/hosts " + err.Error())
|
||||||
}
|
}
|
||||||
// _, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+nodeCfg.Node.Interface, true)
|
// _, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+nodeCfg.Node.Interface, true)
|
||||||
|
@ -197,36 +195,30 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
|
||||||
ncutils.Log("error syncing wg after peer update: " + err.Error())
|
ncutils.Log("error syncing wg after peer update: " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Log(0, "DNS updating /etc/hosts")
|
ncutils.Log("received peer update for node " + cfg.Node.Name + " " + cfg.Node.Network)
|
||||||
|
//skip dns updates if this is a peer update for comms network
|
||||||
|
if cfg.Node.NetworkSettings.IsComms == "yes" {
|
||||||
|
return
|
||||||
|
}
|
||||||
if cfg.Node.DNSOn == "yes" {
|
if cfg.Node.DNSOn == "yes" {
|
||||||
if err := setHostDNS(peerUpdate.DNS, ncutils.IsWindows()); err != nil {
|
if err := setHostDNS(peerUpdate.DNS, cfg.Node.Network, ncutils.IsWindows()); err != nil {
|
||||||
ncutils.Log("error updating /etc/hosts " + err.Error())
|
ncutils.Log("error updating /etc/hosts " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := removeHostDNS(ncutils.IsWindows()); err != nil {
|
if err := removeHostDNS(cfg.Node.Network, ncutils.IsWindows()); err != nil {
|
||||||
ncutils.Log("error removing netmaker profile from /etc/hosts " + err.Error())
|
ncutils.Log("error removing profile from /etc/hosts " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setHostDNS(dns []byte, windows bool) error {
|
func setHostDNS(dns, network string, windows bool) error {
|
||||||
etchosts := "/etc/hosts"
|
etchosts := "/etc/hosts"
|
||||||
if windows {
|
if windows {
|
||||||
etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts"
|
etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts"
|
||||||
}
|
}
|
||||||
tmpfile := "/tmp/dnsdata"
|
dnsdata := strings.NewReader(dns)
|
||||||
if windows {
|
|
||||||
tmpfile = "c:\\windows\\temp\\dnsdata"
|
|
||||||
}
|
|
||||||
if err := os.WriteFile(tmpfile, dns, 0600); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dnsdata, err := os.Open(tmpfile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
profile, err := parser.ParseProfile(dnsdata)
|
profile, err := parser.ParseProfile(dnsdata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -235,7 +227,7 @@ func setHostDNS(dns []byte, windows bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
profile.Name = "netmaker"
|
profile.Name = network
|
||||||
profile.Status = types.Enabled
|
profile.Status = types.Enabled
|
||||||
if err := hosts.ReplaceProfile(profile); err != nil {
|
if err := hosts.ReplaceProfile(profile); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -246,7 +238,7 @@ func setHostDNS(dns []byte, windows bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeHostDNS(windows bool) error {
|
func removeHostDNS(network string, windows bool) error {
|
||||||
etchosts := "/etc/hosts"
|
etchosts := "/etc/hosts"
|
||||||
if windows {
|
if windows {
|
||||||
etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts"
|
etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts"
|
||||||
|
@ -255,7 +247,7 @@ func removeHostDNS(windows bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := hosts.RemoveProfile("netmaker"); err != nil {
|
if err := hosts.RemoveProfile(network); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := hosts.Flush(); err != nil {
|
if err := hosts.Flush(); err != nil {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
<assemblyIdentity
|
<assemblyIdentity
|
||||||
version="0.11.1.0"
|
version="0.12.0.0"
|
||||||
processorArchitecture="*"
|
processorArchitecture="*"
|
||||||
name="netclient.exe"
|
name="netclient.exe"
|
||||||
type="win32"
|
type="win32"
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"OriginalFilename": "",
|
"OriginalFilename": "",
|
||||||
"PrivateBuild": "",
|
"PrivateBuild": "",
|
||||||
"ProductName": "Netclient",
|
"ProductName": "Netclient",
|
||||||
"ProductVersion": "v0.11.1.0",
|
"ProductVersion": "v0.12.0.0",
|
||||||
"SpecialBuild": ""
|
"SpecialBuild": ""
|
||||||
},
|
},
|
||||||
"VarFileInfo": {
|
"VarFileInfo": {
|
||||||
|
|
|
@ -166,21 +166,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ensure you clear any existing interface first
|
// ensure you clear any existing interface first
|
||||||
d, _ := wgclient.Device(deviceiface)
|
RemoveConfGraceful(deviceiface)
|
||||||
startTime := time.Now()
|
|
||||||
for d != nil && d.Name == deviceiface {
|
|
||||||
if err = RemoveConf(deviceiface, false); err != nil { // remove interface first
|
|
||||||
if strings.Contains(err.Error(), "does not exist") {
|
|
||||||
err = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second >> 2)
|
|
||||||
d, _ = wgclient.Device(deviceiface)
|
|
||||||
if time.Now().After(startTime.Add(time.Second << 4)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ApplyConf(node, ifacename, confPath) // Apply initially
|
ApplyConf(node, ifacename, confPath) // Apply initially
|
||||||
ncutils.PrintLog("waiting for interface...", 1) // ensure interface is created
|
ncutils.PrintLog("waiting for interface...", 1) // ensure interface is created
|
||||||
output, _ := ncutils.RunCmd("wg", false)
|
output, _ := ncutils.RunCmd("wg", false)
|
||||||
|
@ -301,6 +287,7 @@ func ApplyConf(node *models.Node, ifacename string, confPath string) error {
|
||||||
var err error
|
var err error
|
||||||
switch os {
|
switch os {
|
||||||
case "windows":
|
case "windows":
|
||||||
|
RemoveConfGraceful(ifacename)
|
||||||
ApplyWindowsConf(confPath)
|
ApplyWindowsConf(confPath)
|
||||||
case "darwin":
|
case "darwin":
|
||||||
ApplyMacOSConf(node, ifacename, confPath)
|
ApplyMacOSConf(node, ifacename, confPath)
|
||||||
|
@ -478,3 +465,29 @@ func UpdatePrivateKey(file, privateKey string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveConfGraceful - Run remove conf and wait for it to actually be gone before proceeding
|
||||||
|
func RemoveConfGraceful(ifacename string) {
|
||||||
|
// ensure you clear any existing interface first
|
||||||
|
wgclient, err := wgctrl.New()
|
||||||
|
if err != nil {
|
||||||
|
ncutils.PrintLog("could not create wgclient", 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer wgclient.Close()
|
||||||
|
d, _ := wgclient.Device(ifacename)
|
||||||
|
startTime := time.Now()
|
||||||
|
for d != nil && d.Name == ifacename {
|
||||||
|
if err = RemoveConf(ifacename, false); err != nil { // remove interface first
|
||||||
|
if strings.Contains(err.Error(), "does not exist") {
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second >> 2)
|
||||||
|
d, _ = wgclient.Device(ifacename)
|
||||||
|
if time.Now().After(startTime.Add(time.Second << 4)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/logger"
|
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
|
@ -72,7 +71,7 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil {
|
if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil {
|
||||||
logger.Log(2, "attempted to remove interface before editing")
|
ncutils.PrintLog("attempted to remove interface before editing", 1)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if node.PostDown != "" {
|
if node.PostDown != "" {
|
||||||
|
@ -81,7 +80,7 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
|
||||||
}
|
}
|
||||||
// set MTU of node interface
|
// set MTU of node interface
|
||||||
if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil {
|
if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil {
|
||||||
logger.Log(2, "failed to create interface with mtu", strconv.Itoa(int(node.MTU)), "-", ifacename)
|
ncutils.PrintLog("failed to create interface with mtu "+strconv.Itoa(int(node.MTU))+"-"+ifacename, 1)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if node.PostUp != "" {
|
if node.PostUp != "" {
|
||||||
|
@ -89,7 +88,7 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
|
||||||
_ = ncutils.RunCmds(runcmds, true)
|
_ = ncutils.RunCmds(runcmds, true)
|
||||||
}
|
}
|
||||||
if node.Address6 != "" && node.IsDualStack == "yes" {
|
if node.Address6 != "" && node.IsDualStack == "yes" {
|
||||||
logger.Log(1, "adding address:", node.Address6)
|
ncutils.PrintLog("adding address: "+node.Address6, 1)
|
||||||
_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/64", true)
|
_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/64", true)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -104,8 +103,8 @@ func RemoveWithoutWGQuick(ifacename string) error {
|
||||||
out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
|
out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
|
||||||
dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
|
dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
|
||||||
if err != nil && !dontprint {
|
if err != nil && !dontprint {
|
||||||
logger.Log(1, "error running command:", ipExec, "link del", ifacename)
|
ncutils.PrintLog("error running command: "+ipExec+" link del "+ifacename, 1)
|
||||||
logger.Log(1, out)
|
ncutils.PrintLog(out, 1)
|
||||||
}
|
}
|
||||||
network := strings.ReplaceAll(ifacename, "nm-", "")
|
network := strings.ReplaceAll(ifacename, "nm-", "")
|
||||||
nodeconf, err := config.ReadConfig(network)
|
nodeconf, err := config.ReadConfig(network)
|
||||||
|
|
BIN
netmaker.png
BIN
netmaker.png
Binary file not shown.
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 16 KiB |
|
@ -10,6 +10,8 @@ import (
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/logger"
|
"github.com/gravitl/netmaker/logger"
|
||||||
"github.com/gravitl/netmaker/logic"
|
"github.com/gravitl/netmaker/logic"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls"
|
||||||
|
"github.com/gravitl/netmaker/logic/acls/nodeacls"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
@ -144,3 +146,21 @@ func SyncServerNetwork(network string) error {
|
||||||
*/
|
*/
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDefaultACLS - runs through each network to see if ACL's are set. If not, goes through each node in network and adds the default ACL
|
||||||
|
func SetDefaultACLS() error {
|
||||||
|
// upgraded systems will not have ACL's set, which is why we need this function
|
||||||
|
nodes, err := logic.GetAllNodes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := range nodes {
|
||||||
|
currentNodeACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID))
|
||||||
|
if (err != nil && (database.IsEmptyRecord(err) || strings.Contains(err.Error(), "no node ACL present"))) || currentNodeACL == nil {
|
||||||
|
if _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID), acls.Allowed); err != nil {
|
||||||
|
logger.Log(1, "could not create a default ACL for node", nodes[i].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue