mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-05 16:57:51 +08:00
Merge branch 'netclient_refactor_latest' of https://github.com/gravitl/netmaker into netclient_refactor_peer_updates
This commit is contained in:
1
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -31,6 +31,7 @@ body:
|
||||
label: Version
|
||||
description: What version are you running?
|
||||
options:
|
||||
- v0.17.1
|
||||
- v0.17.0
|
||||
- v0.16.3
|
||||
- v0.16.2
|
||||
|
3
.github/workflows/buildandrelease.yml
vendored
3
.github/workflows/buildandrelease.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Build
|
||||
@@ -71,4 +71,3 @@ jobs:
|
||||
prerelease: true
|
||||
asset_name: netmaker
|
||||
|
||||
|
||||
|
14
.github/workflows/publish-docker.yml
vendored
14
.github/workflows/publish-docker.yml
vendored
@@ -47,7 +47,9 @@ jobs:
|
||||
platforms: linux/amd64, linux/arm64, linux/arm/v7
|
||||
push: true
|
||||
tags: ${{ github.repository }}:${{ env.TAG }}, ${{ github.repository }}:latest
|
||||
build-args: version=${{ env.TAG }}
|
||||
build-args: |
|
||||
version=${{ env.TAG }}
|
||||
tags=ce
|
||||
|
||||
docker-ee:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -56,7 +58,7 @@ jobs:
|
||||
name: Set tag
|
||||
run: |
|
||||
if [[ -n "${{ github.event.inputs.tag }}" ]]; then
|
||||
docker/build-push-action@v3.tag }}
|
||||
TAG=${{ github.event.inputs.tag }}
|
||||
elif [[ "${{ github.ref_name }}" == 'master' ]]; then
|
||||
TAG="latest"
|
||||
else
|
||||
@@ -71,7 +73,7 @@ jobs:
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
@@ -83,7 +85,9 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64, linux/arm64, linux/arm/v7
|
||||
platforms: linux/amd64, linux/arm64
|
||||
push: true
|
||||
tags: ${{ github.repository }}:${{ env.TAG }}-ee
|
||||
build-args: version=${{ env.TAG }}, tags="-tags=ee"
|
||||
build-args: |
|
||||
version=${{ env.TAG }}
|
||||
tags=ee
|
||||
|
29
.github/workflows/test.yml
vendored
29
.github/workflows/test.yml
vendored
@@ -1,8 +1,9 @@
|
||||
name: Integration Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, reopened]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -11,7 +12,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Build
|
||||
@@ -23,13 +24,29 @@ jobs:
|
||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build main.go
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
|
||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
|
||||
nmctl:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Build
|
||||
run: |
|
||||
cd cli
|
||||
GOOS=linux GOARCH=amd64 go build -o nmctl
|
||||
GOOS=darwin GOARCH=amd64 go build -o nmctl
|
||||
GOOS=darwin GOARCH=arm64 go build -o nmctl
|
||||
GOOS=windows GOARCH=amd64 go build -o nmctl
|
||||
linux-gui:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Build
|
||||
@@ -43,7 +60,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Build mac
|
||||
@@ -55,7 +72,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Mysys2 setup
|
||||
@@ -75,7 +92,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: run tests
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,7 @@ netmaker-arm
|
||||
netmaker-arm64
|
||||
netmaker-32
|
||||
netmaker-amd64
|
||||
cli/nmctl
|
||||
netclient/netclient
|
||||
netclient/netclient.syso
|
||||
netclient/build
|
||||
@@ -22,3 +23,4 @@ data/
|
||||
.vscode/
|
||||
.idea/
|
||||
netmaker.exe
|
||||
netmaker.code-workspace
|
||||
|
@@ -7,7 +7,7 @@ COPY . .
|
||||
ENV GO111MODULE=auto
|
||||
|
||||
RUN apk add git
|
||||
RUN GOOS=linux CGO_ENABLED=1 go build ${tags} -ldflags="-s -X 'main.version=${version}'" .
|
||||
RUN GOOS=linux CGO_ENABLED=1 go build -ldflags="-s -X 'main.version=${version}'" -tags ${tags} .
|
||||
# RUN go build -tags=ee . -o netmaker main.go
|
||||
FROM alpine:3.16.2
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/gravitl/netmaker/releases">
|
||||
<img src="https://img.shields.io/badge/Version-0.17.0-informational?style=flat-square" />
|
||||
<img src="https://img.shields.io/badge/Version-0.17.1-informational?style=flat-square" />
|
||||
</a>
|
||||
<a href="https://hub.docker.com/r/gravitl/netmaker/tags">
|
||||
<img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />
|
||||
@@ -57,7 +57,7 @@
|
||||
3. (optional) Prepare DNS - Set a wildcard subdomain in your DNS for Netmaker, e.g. *.netmaker.example.com
|
||||
4. Run the script:
|
||||
|
||||
`sudo wget -qO /root/nm-quick-interactive.sh https://raw.githubusercontent.com/gravitl/netmaker/test_v0.17.0_compose/scripts/nm-quick-interactive.sh && sudo chmod +x /root/nm-quick-interactive.sh && sudo /root/nm-quick-interactive.sh`
|
||||
`sudo wget -qO /root/nm-quick-interactive.sh https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick-interactive.sh && sudo chmod +x /root/nm-quick-interactive.sh && sudo /root/nm-quick-interactive.sh`
|
||||
|
||||
This script gives you the option to deploy the Community or Enterprise version of Netmaker. If deploying Enterprise, you get a free account with a 50 node limit by default. It also gives you the option to use your own domain (recommended) or an auto-generated domain.
|
||||
|
||||
|
133
auth/auth.go
133
auth/auth.go
@@ -3,17 +3,21 @@ package auth
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/logic"
|
||||
"github.com/gravitl/netmaker/logic/pro/netcache"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// == consts ==
|
||||
@@ -30,6 +34,7 @@ const (
|
||||
auth_key = "netmaker_auth"
|
||||
user_signin_length = 16
|
||||
node_signin_length = 64
|
||||
headless_signin_length = 32
|
||||
)
|
||||
|
||||
// OAuthUser - generic OAuth strategy user
|
||||
@@ -41,7 +46,10 @@ type OAuthUser struct {
|
||||
AccessToken string `json:"accesstoken" bson:"accesstoken"`
|
||||
}
|
||||
|
||||
var auth_provider *oauth2.Config
|
||||
var (
|
||||
auth_provider *oauth2.Config
|
||||
upgrader = websocket.Upgrader{}
|
||||
)
|
||||
|
||||
func getCurrentAuthFunctions() map[string]interface{} {
|
||||
var authInfo = servercfg.GetAuthProviderInfo()
|
||||
@@ -71,10 +79,6 @@ func InitializeAuthProvider() string {
|
||||
logger.Log(0, err.Error())
|
||||
return ""
|
||||
}
|
||||
var currentFrontendURL = servercfg.GetFrontendURL()
|
||||
if currentFrontendURL == "" {
|
||||
return ""
|
||||
}
|
||||
var authInfo = servercfg.GetAuthProviderInfo()
|
||||
var serverConn = servercfg.GetAPIHost()
|
||||
if strings.Contains(serverConn, "localhost") || strings.Contains(serverConn, "127.0.0.1") {
|
||||
@@ -94,12 +98,11 @@ func InitializeAuthProvider() string {
|
||||
return authInfo[0]
|
||||
}
|
||||
|
||||
// Not included in API reference as part of the OAuth process itself.
|
||||
// HandleAuthCallback - handles oauth callback
|
||||
// Note: not included in API reference as part of the OAuth process itself.
|
||||
func HandleAuthCallback(w http.ResponseWriter, r *http.Request) {
|
||||
if auth_provider == nil {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintln(w, oauthNotConfigured)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
var functions = getCurrentAuthFunctions()
|
||||
@@ -108,9 +111,17 @@ func HandleAuthCallback(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
state, _ := getStateAndCode(r)
|
||||
_, err := netcache.Get(state) // if in netcache proceeed with node registration login
|
||||
if err == nil || len(state) == node_signin_length || (err != nil && strings.Contains(err.Error(), "expired")) {
|
||||
logger.Log(0, "proceeding with node SSO callback")
|
||||
HandleNodeSSOCallback(w, r)
|
||||
if err == nil || errors.Is(err, netcache.ErrExpired) {
|
||||
switch len(state) {
|
||||
case node_signin_length:
|
||||
logger.Log(0, "proceeding with node SSO callback")
|
||||
HandleNodeSSOCallback(w, r)
|
||||
case headless_signin_length:
|
||||
logger.Log(0, "proceeding with headless SSO callback")
|
||||
HandleHeadlessSSOCallback(w, r)
|
||||
default:
|
||||
logger.Log(1, "invalid state length: ", fmt.Sprintf("%d", len(state)))
|
||||
}
|
||||
} else { // handle normal login
|
||||
functions[handle_callback].(func(http.ResponseWriter, *http.Request))(w, r)
|
||||
}
|
||||
@@ -120,25 +131,23 @@ func HandleAuthCallback(w http.ResponseWriter, r *http.Request) {
|
||||
//
|
||||
// Handles OAuth login.
|
||||
//
|
||||
// Schemes: https
|
||||
// Schemes: https
|
||||
//
|
||||
// Security:
|
||||
// oauth
|
||||
// Security:
|
||||
// oauth
|
||||
func HandleAuthLogin(w http.ResponseWriter, r *http.Request) {
|
||||
if auth_provider == nil {
|
||||
var referer = r.Header.Get("referer")
|
||||
if referer != "" {
|
||||
http.Redirect(w, r, referer+"login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintln(w, oauthNotConfigured)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
var functions = getCurrentAuthFunctions()
|
||||
if functions == nil {
|
||||
return
|
||||
}
|
||||
if servercfg.GetFrontendURL() == "" {
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
functions[handle_login].(func(http.ResponseWriter, *http.Request))(w, r)
|
||||
}
|
||||
|
||||
@@ -152,6 +161,80 @@ func IsOauthUser(user *models.User) error {
|
||||
return bCryptErr
|
||||
}
|
||||
|
||||
// HandleHeadlessSSO - handles the OAuth login flow for headless interfaces such as Netmaker CLI via websocket
|
||||
func HandleHeadlessSSO(w http.ResponseWriter, r *http.Request) {
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Log(0, "error during connection upgrade for headless sign-in:", err.Error())
|
||||
return
|
||||
}
|
||||
if conn == nil {
|
||||
logger.Log(0, "failed to establish web-socket connection during headless sign-in")
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
req := &netcache.CValue{User: "", Pass: ""}
|
||||
stateStr := logic.RandomString(headless_signin_length)
|
||||
if err = netcache.Set(stateStr, req); err != nil {
|
||||
logger.Log(0, "Failed to process sso request -", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
timeout := make(chan bool, 1)
|
||||
answer := make(chan string, 1)
|
||||
defer close(answer)
|
||||
defer close(timeout)
|
||||
|
||||
if auth_provider == nil {
|
||||
if err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
|
||||
logger.Log(0, "error during message writing:", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
redirectUrl = fmt.Sprintf("https://%s/api/oauth/register/%s", servercfg.GetAPIConnString(), stateStr)
|
||||
if err = conn.WriteMessage(websocket.TextMessage, []byte(redirectUrl)); err != nil {
|
||||
logger.Log(0, "error during message writing:", err.Error())
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
cachedReq, err := netcache.Get(stateStr)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "expired") {
|
||||
logger.Log(0, "timeout occurred while waiting for SSO")
|
||||
timeout <- true
|
||||
break
|
||||
}
|
||||
continue
|
||||
} else if cachedReq.Pass != "" {
|
||||
logger.Log(0, "SSO process completed for user ", cachedReq.User)
|
||||
answer <- cachedReq.Pass
|
||||
break
|
||||
}
|
||||
time.Sleep(500) // try it 2 times per second to see if auth is completed
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-answer:
|
||||
if err = conn.WriteMessage(websocket.TextMessage, []byte(result)); err != nil {
|
||||
logger.Log(0, "Error during message writing:", err.Error())
|
||||
}
|
||||
case <-timeout:
|
||||
logger.Log(0, "Authentication server time out for headless SSO login")
|
||||
if err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
|
||||
logger.Log(0, "Error during message writing:", err.Error())
|
||||
}
|
||||
}
|
||||
if err = netcache.Del(stateStr); err != nil {
|
||||
logger.Log(0, "failed to remove SSO cache entry", err.Error())
|
||||
}
|
||||
if err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
|
||||
logger.Log(0, "write close:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// == private methods ==
|
||||
|
||||
func addUser(email string) error {
|
||||
@@ -169,7 +252,7 @@ func addUser(email string) error {
|
||||
Password: newPass,
|
||||
}
|
||||
if !hasAdmin { // must be first attempt, create an admin
|
||||
if newUser, err = logic.CreateAdmin(newUser); err != nil {
|
||||
if err = logic.CreateAdmin(&newUser); err != nil {
|
||||
logger.Log(1, "error creating admin from user,", email, "; user not added")
|
||||
} else {
|
||||
logger.Log(1, "admin created from user,", email, "; was first user added")
|
||||
@@ -177,7 +260,7 @@ func addUser(email string) error {
|
||||
} else { // otherwise add to db as admin..?
|
||||
// TODO: add ability to add users with preemptive permissions
|
||||
newUser.IsAdmin = false
|
||||
if newUser, err = logic.CreateUser(newUser); err != nil {
|
||||
if err = logic.CreateUser(&newUser); err != nil {
|
||||
logger.Log(1, "error creating user,", email, "; user not added")
|
||||
} else {
|
||||
logger.Log(0, "user created from ", email)
|
||||
|
@@ -37,16 +37,13 @@ func initAzureAD(redirectURL string, clientID string, clientSecret string) {
|
||||
|
||||
func handleAzureLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||
if auth_provider == nil && servercfg.GetFrontendURL() != "" {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
return
|
||||
} else if auth_provider == nil {
|
||||
fmt.Fprintf(w, "%s", []byte("no frontend URL was provided and an OAuth login was attempted\nplease reconfigure server to use OAuth or use basic credentials"))
|
||||
if auth_provider == nil {
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logic.SetState(oauth_state_string); err != nil {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -60,7 +57,7 @@ func handleAzureCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var content, err = getAzureUserInfo(rState, rCode)
|
||||
if err != nil {
|
||||
logger.Log(1, "error when getting user info from azure:", err.Error())
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
_, err = logic.GetUser(content.UserPrincipalName)
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package auth
|
||||
|
||||
import "net/http"
|
||||
|
||||
// == define error HTML here ==
|
||||
const oauthNotConfigured = `<!DOCTYPE html><html>
|
||||
<body>
|
||||
@@ -7,3 +9,10 @@ const oauthNotConfigured = `<!DOCTYPE html><html>
|
||||
<p>Please visit the docs <a href="https://docs.netmaker.org/oauth.html" target="_blank" rel="noopener">here</a> to learn how to.</p>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
// handleOauthNotConfigured - returns an appropriate html page when oauth is not configured on netmaker server but an oauth login was attempted
|
||||
func handleOauthNotConfigured(response http.ResponseWriter) {
|
||||
response.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
response.Write([]byte(oauthNotConfigured))
|
||||
}
|
||||
|
@@ -37,16 +37,13 @@ func initGithub(redirectURL string, clientID string, clientSecret string) {
|
||||
|
||||
func handleGithubLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||
if auth_provider == nil && servercfg.GetFrontendURL() != "" {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
return
|
||||
} else if auth_provider == nil {
|
||||
fmt.Fprintf(w, "%s", []byte("no frontend URL was provided and an OAuth login was attempted\nplease reconfigure server to use OAuth or use basic credentials"))
|
||||
if auth_provider == nil {
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logic.SetState(oauth_state_string); err != nil {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -60,7 +57,7 @@ func handleGithubCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var content, err = getGithubUserInfo(rState, rCode)
|
||||
if err != nil {
|
||||
logger.Log(1, "error when getting user info from github:", err.Error())
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
_, err = logic.GetUser(content.Login)
|
||||
|
@@ -38,16 +38,13 @@ func initGoogle(redirectURL string, clientID string, clientSecret string) {
|
||||
|
||||
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||
if auth_provider == nil && servercfg.GetFrontendURL() != "" {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
return
|
||||
} else if auth_provider == nil {
|
||||
fmt.Fprintf(w, "%s", []byte("no frontend URL was provided and an OAuth login was attempted\nplease reconfigure server to use OAuth or use basic credentials"))
|
||||
if auth_provider == nil {
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logic.SetState(oauth_state_string); err != nil {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,7 +59,7 @@ func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var content, err = getGoogleUserInfo(rState, rCode)
|
||||
if err != nil {
|
||||
logger.Log(1, "error when getting user info from google:", err.Error())
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
_, err = logic.GetUser(content.Email)
|
||||
|
93
auth/headless_callback.go
Normal file
93
auth/headless_callback.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/logic"
|
||||
"github.com/gravitl/netmaker/logic/pro/netcache"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
// HandleHeadlessSSOCallback - handle OAuth callback for headless logins such as Netmaker CLI
|
||||
func HandleHeadlessSSOCallback(w http.ResponseWriter, r *http.Request) {
|
||||
functions := getCurrentAuthFunctions()
|
||||
if functions == nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("bad conf"))
|
||||
logger.Log(0, "Missing Oauth config in HandleHeadlessSSOCallback")
|
||||
return
|
||||
}
|
||||
state, code := getStateAndCode(r)
|
||||
|
||||
userClaims, err := functions[get_user_info].(func(string, string) (*OAuthUser, error))(state, code)
|
||||
if err != nil {
|
||||
logger.Log(0, "error when getting user info from callback:", err.Error())
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("Failed to retrieve OAuth user claims"))
|
||||
return
|
||||
}
|
||||
|
||||
if code == "" || state == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("Wrong params"))
|
||||
logger.Log(0, "Missing params in HandleHeadlessSSOCallback")
|
||||
return
|
||||
}
|
||||
|
||||
// all responses should be in html format from here on out
|
||||
w.Header().Add("content-type", "text/html; charset=utf-8")
|
||||
|
||||
// retrieve machinekey from state cache
|
||||
reqKeyIf, machineKeyFoundErr := netcache.Get(state)
|
||||
if machineKeyFoundErr != nil {
|
||||
logger.Log(0, "requested machine state key expired before authorisation completed -", machineKeyFoundErr.Error())
|
||||
response := returnErrTemplate("", "requested machine state key expired before authorisation completed", state, reqKeyIf)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write(response)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = logic.GetUser(userClaims.getUserName())
|
||||
if err != nil { // user must not exists, so try to make one
|
||||
if err = addUser(userClaims.getUserName()); err != nil {
|
||||
logger.Log(1, "could not create new user: ", userClaims.getUserName())
|
||||
return
|
||||
}
|
||||
}
|
||||
newPass, fetchErr := fetchPassValue("")
|
||||
if fetchErr != nil {
|
||||
return
|
||||
}
|
||||
jwt, jwtErr := logic.VerifyAuthRequest(models.UserAuthParams{
|
||||
UserName: userClaims.getUserName(),
|
||||
Password: newPass,
|
||||
})
|
||||
if jwtErr != nil {
|
||||
logger.Log(1, "could not parse jwt for user", userClaims.getUserName())
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log(1, "headless SSO login by user:", userClaims.getUserName())
|
||||
|
||||
// Send OK to user in the browser
|
||||
var response bytes.Buffer
|
||||
if err := ssoCallbackTemplate.Execute(&response, ssoCallbackTemplateConfig{
|
||||
User: userClaims.getUserName(),
|
||||
Verb: "Authenticated",
|
||||
}); err != nil {
|
||||
logger.Log(0, "Could not render SSO callback template ", err.Error())
|
||||
response := returnErrTemplate(userClaims.getUserName(), "Could not render SSO callback template", state, reqKeyIf)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write(response)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(response.Bytes())
|
||||
}
|
||||
reqKeyIf.Pass = fmt.Sprintf("JWT: %s", jwt)
|
||||
if err = netcache.Set(state, reqKeyIf); err != nil {
|
||||
logger.Log(0, "failed to set netcache for user", reqKeyIf.User, "-", err.Error())
|
||||
}
|
||||
}
|
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/gravitl/netmaker/logic/pro/netcache"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/models/promodels"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -41,7 +40,7 @@ func HandleNodeSSOCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var userClaims, err = functions[get_user_info].(func(string, string) (*OAuthUser, error))(state, code)
|
||||
if err != nil {
|
||||
logger.Log(0, "error when getting user info from callback:", err.Error())
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -135,7 +134,9 @@ func setNetcache(ncache *netcache.CValue, state string) error {
|
||||
|
||||
func returnErrTemplate(uname, message, state string, ncache *netcache.CValue) []byte {
|
||||
var response bytes.Buffer
|
||||
ncache.Pass = message
|
||||
if ncache != nil {
|
||||
ncache.Pass = message
|
||||
}
|
||||
err := ssoErrCallbackTemplate.Execute(&response, ssoCallbackTemplateConfig{
|
||||
User: uname,
|
||||
Verb: message,
|
||||
@@ -257,5 +258,5 @@ func isUserIsAllowed(username, network string, shouldAddUser bool) (*models.User
|
||||
}
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
return user, nil
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -45,7 +44,7 @@ func SessionHandler(conn *websocket.Conn) {
|
||||
req.Pass = ""
|
||||
req.User = ""
|
||||
// Add any extra parameter provided in the configuration to the Authorize Endpoint request??
|
||||
stateStr := hex.EncodeToString([]byte(logic.RandomString(node_signin_length)))
|
||||
stateStr := logic.RandomString(node_signin_length)
|
||||
if err := netcache.Set(stateStr, req); err != nil {
|
||||
logger.Log(0, "Failed to process sso request -", err.Error())
|
||||
return
|
||||
|
11
auth/oidc.go
11
auth/oidc.go
@@ -50,16 +50,13 @@ func initOIDC(redirectURL string, clientID string, clientSecret string, issuer s
|
||||
|
||||
func handleOIDCLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var oauth_state_string = logic.RandomString(user_signin_length)
|
||||
if auth_provider == nil && servercfg.GetFrontendURL() != "" {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
return
|
||||
} else if auth_provider == nil {
|
||||
fmt.Fprintf(w, "%s", []byte("no frontend URL was provided and an OAuth login was attempted\nplease reconfigure server to use OAuth or use basic credentials"))
|
||||
if auth_provider == nil {
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
|
||||
if err := logic.SetState(oauth_state_string); err != nil {
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
var url = auth_provider.AuthCodeURL(oauth_state_string)
|
||||
@@ -73,7 +70,7 @@ func handleOIDCCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var content, err = getOIDCUserInfo(rState, rCode)
|
||||
if err != nil {
|
||||
logger.Log(1, "error when getting user info from callback:", err.Error())
|
||||
http.Redirect(w, r, servercfg.GetFrontendURL()+"/login?oauth=callback-error", http.StatusTemporaryRedirect)
|
||||
handleOauthNotConfigured(w)
|
||||
return
|
||||
}
|
||||
_, err = logic.GetUser(content.Email)
|
||||
|
46
cli/cmd/acl/allow.go
Normal file
46
cli/cmd/acl/allow.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/logic/acls"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var aclAllowCmd = &cobra.Command{
|
||||
Use: "allow [NETWORK NAME] [FROM_NODE_NAME] [TO_NODE_NAME]",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Short: "Allow access from one node to another",
|
||||
Long: `Allow access from one node to another`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
nameIDMap := make(map[string]string)
|
||||
for _, node := range *functions.GetNodes(args[0]) {
|
||||
nameIDMap[strings.ToLower(node.Name)] = node.ID
|
||||
}
|
||||
fromNodeID, ok := nameIDMap[strings.ToLower(args[1])]
|
||||
if !ok {
|
||||
log.Fatalf("Node %s doesn't exist", args[1])
|
||||
}
|
||||
toNodeID, ok := nameIDMap[strings.ToLower(args[2])]
|
||||
if !ok {
|
||||
log.Fatalf("Node %s doesn't exist", args[2])
|
||||
}
|
||||
payload := acls.ACLContainer(map[acls.AclID]acls.ACL{
|
||||
acls.AclID(fromNodeID): map[acls.AclID]byte{
|
||||
acls.AclID(toNodeID): acls.Allowed,
|
||||
},
|
||||
acls.AclID(toNodeID): map[acls.AclID]byte{
|
||||
acls.AclID(fromNodeID): acls.Allowed,
|
||||
},
|
||||
})
|
||||
functions.UpdateACL(args[0], &payload)
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(aclAllowCmd)
|
||||
}
|
46
cli/cmd/acl/deny.go
Normal file
46
cli/cmd/acl/deny.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/logic/acls"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var aclDenyCmd = &cobra.Command{
|
||||
Use: "deny [NETWORK NAME] [FROM_NODE_NAME] [TO_NODE_NAME]",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Short: "Deny access from one node to another",
|
||||
Long: `Deny access from one node to another`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
nameIDMap := make(map[string]string)
|
||||
for _, node := range *functions.GetNodes(args[0]) {
|
||||
nameIDMap[strings.ToLower(node.Name)] = node.ID
|
||||
}
|
||||
fromNodeID, ok := nameIDMap[strings.ToLower(args[1])]
|
||||
if !ok {
|
||||
log.Fatalf("Node %s doesn't exist", args[1])
|
||||
}
|
||||
toNodeID, ok := nameIDMap[strings.ToLower(args[2])]
|
||||
if !ok {
|
||||
log.Fatalf("Node %s doesn't exist", args[2])
|
||||
}
|
||||
payload := acls.ACLContainer(map[acls.AclID]acls.ACL{
|
||||
acls.AclID(fromNodeID): map[acls.AclID]byte{
|
||||
acls.AclID(toNodeID): acls.NotAllowed,
|
||||
},
|
||||
acls.AclID(toNodeID): map[acls.AclID]byte{
|
||||
acls.AclID(fromNodeID): acls.NotAllowed,
|
||||
},
|
||||
})
|
||||
functions.UpdateACL(args[0], &payload)
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(aclDenyCmd)
|
||||
}
|
46
cli/cmd/acl/list.go
Normal file
46
cli/cmd/acl/list.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/logic/acls"
|
||||
"github.com/guumaster/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var aclListCmd = &cobra.Command{
|
||||
Use: "list [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "List all ACLs associated with a network",
|
||||
Long: `List all ACLs associated with a network`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
aclSource := (map[acls.AclID]acls.ACL)(*functions.GetACL(args[0]))
|
||||
nodes := functions.GetNodes(args[0])
|
||||
idNameMap := make(map[string]string)
|
||||
for _, node := range *nodes {
|
||||
idNameMap[node.ID] = node.Name
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"From", "To", "Status"})
|
||||
for id, acl := range aclSource {
|
||||
for k, v := range (map[acls.AclID]byte)(acl) {
|
||||
row := []string{idNameMap[string(id)], idNameMap[string(k)]}
|
||||
switch v {
|
||||
case acls.NotAllowed:
|
||||
row = append(row, "Not Allowed")
|
||||
case acls.NotPresent:
|
||||
row = append(row, "Not Present")
|
||||
case acls.Allowed:
|
||||
row = append(row, "Allowed")
|
||||
}
|
||||
table.Append(row)
|
||||
}
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(aclListCmd)
|
||||
}
|
38
cli/cmd/acl/root.go
Normal file
38
cli/cmd/acl/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "acl",
|
||||
Short: "Manage Access Control Lists (ACLs)",
|
||||
Long: `Manage Access Control Lists (ACLs)`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
20
cli/cmd/context/delete.go
Normal file
20
cli/cmd/context/delete.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var contextDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Delete a context",
|
||||
Long: `Delete a context`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
config.DeleteContext(args[0])
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(contextDeleteCmd)
|
||||
}
|
20
cli/cmd/context/list.go
Normal file
20
cli/cmd/context/list.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var contextListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List all contexts",
|
||||
Long: `List all contexts`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
config.ListAll()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(contextListCmd)
|
||||
}
|
38
cli/cmd/context/root.go
Normal file
38
cli/cmd/context/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "context",
|
||||
Short: "Manage various netmaker server configurations",
|
||||
Long: `Manage various netmaker server configurations`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
48
cli/cmd/context/set.go
Normal file
48
cli/cmd/context/set.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoint string
|
||||
username string
|
||||
password string
|
||||
masterKey string
|
||||
sso bool
|
||||
)
|
||||
|
||||
var contextSetCmd = &cobra.Command{
|
||||
Use: "set [NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Create a context or update an existing one",
|
||||
Long: `Create a context or update an existing one`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := config.Context{
|
||||
Endpoint: endpoint,
|
||||
Username: username,
|
||||
Password: password,
|
||||
MasterKey: masterKey,
|
||||
SSO: sso,
|
||||
}
|
||||
if ctx.Username == "" && ctx.MasterKey == "" && !ctx.SSO {
|
||||
cmd.Usage()
|
||||
log.Fatal("Either username/password or master key is required")
|
||||
}
|
||||
config.SetContext(args[0], ctx)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
contextSetCmd.Flags().StringVar(&endpoint, "endpoint", "", "Endpoint of the API Server")
|
||||
contextSetCmd.MarkFlagRequired("endpoint")
|
||||
contextSetCmd.Flags().StringVar(&username, "username", "", "Username")
|
||||
contextSetCmd.Flags().StringVar(&password, "password", "", "Password")
|
||||
contextSetCmd.MarkFlagsRequiredTogether("username", "password")
|
||||
contextSetCmd.Flags().BoolVar(&sso, "sso", false, "Login via Single Sign On (SSO) ?")
|
||||
contextSetCmd.Flags().StringVar(&masterKey, "master_key", "", "Master Key")
|
||||
rootCmd.AddCommand(contextSetCmd)
|
||||
}
|
20
cli/cmd/context/use.go
Normal file
20
cli/cmd/context/use.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var contextUseCmd = &cobra.Command{
|
||||
Use: "use [NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Set the current context",
|
||||
Long: `Set the current context`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
config.SetCurrentContext(args[0])
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(contextUseCmd)
|
||||
}
|
33
cli/cmd/dns/create.go
Normal file
33
cli/cmd/dns/create.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var dnsCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Create a DNS entry",
|
||||
Long: `Create a DNS entry`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if address == "" && address6 == "" {
|
||||
log.Fatal("Either IPv4 or IPv6 address is required")
|
||||
}
|
||||
dnsEntry := &models.DNSEntry{Name: dnsName, Address: address, Address6: address6, Network: networkName}
|
||||
functions.PrettyPrint(functions.CreateDNS(networkName, dnsEntry))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
dnsCreateCmd.Flags().StringVar(&dnsName, "name", "", "Name of the DNS entry")
|
||||
dnsCreateCmd.MarkFlagRequired("name")
|
||||
dnsCreateCmd.Flags().StringVar(&networkName, "network", "", "Name of the Network")
|
||||
dnsCreateCmd.MarkFlagRequired("network")
|
||||
dnsCreateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 Address")
|
||||
dnsCreateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 Address")
|
||||
rootCmd.AddCommand(dnsCreateCmd)
|
||||
}
|
20
cli/cmd/dns/delete.go
Normal file
20
cli/cmd/dns/delete.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var dnsDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NETWORK NAME] [DOMAIN NAME]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete a DNS entry",
|
||||
Long: `Delete a DNS entry`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteDNS(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(dnsDeleteCmd)
|
||||
}
|
9
cli/cmd/dns/flags.go
Normal file
9
cli/cmd/dns/flags.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package dns
|
||||
|
||||
var (
|
||||
dnsName string
|
||||
address string
|
||||
address6 string
|
||||
networkName string
|
||||
dnsType string
|
||||
)
|
47
cli/cmd/dns/list.go
Normal file
47
cli/cmd/dns/list.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/guumaster/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var dnsListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List DNS entries",
|
||||
Long: `List DNS entries`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var data []models.DNSEntry
|
||||
if networkName != "" {
|
||||
switch dnsType {
|
||||
case "node":
|
||||
data = *functions.GetNodeDNS(networkName)
|
||||
case "custom":
|
||||
data = *functions.GetCustomDNS(networkName)
|
||||
case "network", "":
|
||||
data = *functions.GetNetworkDNS(networkName)
|
||||
default:
|
||||
fmt.Println("Invalid DNS type provided ", dnsType)
|
||||
}
|
||||
} else {
|
||||
data = *functions.GetDNS()
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Name", "Network", "IPv4 Address", "IPv6 Address"})
|
||||
for _, d := range data {
|
||||
table.Append([]string{d.Name, d.Network, d.Address, d.Address6})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
dnsListCmd.Flags().StringVar(&networkName, "network", "", "Network name")
|
||||
dnsListCmd.Flags().StringVar(&dnsType, "type", "", "Type of DNS records to fetch ENUM(node, custom, network)")
|
||||
rootCmd.AddCommand(dnsListCmd)
|
||||
}
|
22
cli/cmd/dns/push.go
Normal file
22
cli/cmd/dns/push.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var dnsPushCmd = &cobra.Command{
|
||||
Use: "push",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Push latest DNS entries",
|
||||
Long: `Push latest DNS entries`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(*functions.PushDNS())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(dnsPushCmd)
|
||||
}
|
38
cli/cmd/dns/root.go
Normal file
38
cli/cmd/dns/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "dns",
|
||||
Short: "Manage DNS entries associated with a network",
|
||||
Long: `Manage DNS entries associated with a network`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
22
cli/cmd/ext_client/config.go
Normal file
22
cli/cmd/ext_client/config.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var extClientConfigCmd = &cobra.Command{
|
||||
Use: "config [NETWORK NAME] [EXTERNAL CLIENT ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Get an External Client Configuration",
|
||||
Long: `Get an External Client Configuration`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(functions.GetExtClientConfig(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(extClientConfigCmd)
|
||||
}
|
26
cli/cmd/ext_client/create.go
Normal file
26
cli/cmd/ext_client/create.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var extClientID string
|
||||
|
||||
var extClientCreateCmd = &cobra.Command{
|
||||
Use: "create [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Create an External Client",
|
||||
Long: `Create an External Client`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.CreateExtClient(args[0], args[1], extClientID)
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
extClientCreateCmd.Flags().StringVar(&extClientID, "id", "", "ID of the external client")
|
||||
rootCmd.AddCommand(extClientCreateCmd)
|
||||
}
|
20
cli/cmd/ext_client/delete.go
Normal file
20
cli/cmd/ext_client/delete.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var extClientDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NETWORK NAME] [EXTERNAL CLIENT ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete an External Client",
|
||||
Long: `Delete an External Client`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteExtClient(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(extClientDeleteCmd)
|
||||
}
|
20
cli/cmd/ext_client/get.go
Normal file
20
cli/cmd/ext_client/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var extClientGetCmd = &cobra.Command{
|
||||
Use: "get [NETWORK NAME] [EXTERNAL CLIENT ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Get an External Client",
|
||||
Long: `Get an External Client`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetExtClient(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(extClientGetCmd)
|
||||
}
|
40
cli/cmd/ext_client/list.go
Normal file
40
cli/cmd/ext_client/list.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/guumaster/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkName string
|
||||
|
||||
var extClientListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List External Clients",
|
||||
Long: `List External Clients`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var data []models.ExtClient
|
||||
if networkName != "" {
|
||||
data = *functions.GetNetworkExtClients(networkName)
|
||||
} else {
|
||||
data = *functions.GetAllExtClients()
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Client ID", "Network", "IPv4 Address", "IPv6 Address", "Enabled", "Last Modified"})
|
||||
for _, d := range data {
|
||||
table.Append([]string{d.ClientID, d.Network, d.Address, d.Address6, strconv.FormatBool(d.Enabled), time.Unix(d.LastModified, 0).String()})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
extClientListCmd.Flags().StringVar(&networkName, "network", "", "Network name")
|
||||
rootCmd.AddCommand(extClientListCmd)
|
||||
}
|
38
cli/cmd/ext_client/root.go
Normal file
38
cli/cmd/ext_client/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "ext_client",
|
||||
Short: "Manage External Clients",
|
||||
Long: `Manage External Clients`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
71
cli/cmd/ext_client/update.go
Normal file
71
cli/cmd/ext_client/update.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package ext_client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
extClientUpdateFile string
|
||||
description string
|
||||
privateKey string
|
||||
publicKey string
|
||||
address string
|
||||
address6 string
|
||||
ingressGatewayID string
|
||||
ingressGatewayEndpoint string
|
||||
ownerID string
|
||||
)
|
||||
|
||||
var extClientUpdateCmd = &cobra.Command{
|
||||
Use: "update [NETWORK NAME] [EXTERNAL CLIENT ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Update an External Client",
|
||||
Long: `Update an External Client`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
network = args[0]
|
||||
clientID = args[1]
|
||||
extClient = &models.ExtClient{}
|
||||
)
|
||||
if extClientUpdateFile != "" {
|
||||
content, err := os.ReadFile(extClientUpdateFile)
|
||||
if err != nil {
|
||||
log.Fatal("Error when opening file: ", err)
|
||||
}
|
||||
if err := json.Unmarshal(content, extClient); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
extClient.ClientID = clientID
|
||||
extClient.Description = description
|
||||
extClient.PrivateKey = privateKey
|
||||
extClient.PublicKey = publicKey
|
||||
extClient.Network = network
|
||||
extClient.Address = address
|
||||
extClient.Address6 = address6
|
||||
extClient.IngressGatewayID = ingressGatewayID
|
||||
extClient.IngressGatewayEndpoint = ingressGatewayEndpoint
|
||||
extClient.OwnerID = ownerID
|
||||
}
|
||||
functions.PrettyPrint(functions.UpdateExtClient(network, clientID, extClient))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
extClientUpdateCmd.Flags().StringVar(&extClientUpdateFile, "file", "", "Filepath of updated external client definition in JSON")
|
||||
extClientUpdateCmd.Flags().StringVar(&description, "desc", "", "Description of the external client")
|
||||
extClientUpdateCmd.Flags().StringVar(&privateKey, "private_key", "", "Filepath of updated external client definition in JSON")
|
||||
extClientUpdateCmd.Flags().StringVar(&publicKey, "public_key", "", "Filepath of updated external client definition in JSON")
|
||||
extClientUpdateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 address of the external client")
|
||||
extClientUpdateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 address of the external client")
|
||||
extClientUpdateCmd.Flags().StringVar(&ingressGatewayID, "ingress_gateway_id", "", "ID of the ingress gateway")
|
||||
extClientUpdateCmd.Flags().StringVar(&ingressGatewayEndpoint, "ingress_gateway_endpoint", "", "Endpoint of the ingress gateway")
|
||||
extClientUpdateCmd.Flags().StringVar(&ownerID, "owner_id", "", "External Client owner's ID")
|
||||
rootCmd.AddCommand(extClientUpdateCmd)
|
||||
}
|
35
cli/cmd/keys/create.go
Normal file
35
cli/cmd/keys/create.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var keyName string
|
||||
|
||||
var keysCreateCmd = &cobra.Command{
|
||||
Use: "create [NETWORK NAME] [NUM USES]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Create an access key",
|
||||
Long: `Create an access key`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
keyUses, err := strconv.ParseInt(args[1], 10, 64)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
key := &models.AccessKey{Uses: int(keyUses)}
|
||||
if keyName != "" {
|
||||
key.Name = keyName
|
||||
}
|
||||
functions.PrettyPrint(functions.CreateKey(args[0], key))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
keysCreateCmd.Flags().StringVar(&keyName, "name", "", "Name of the key")
|
||||
rootCmd.AddCommand(keysCreateCmd)
|
||||
}
|
23
cli/cmd/keys/delete.go
Normal file
23
cli/cmd/keys/delete.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var keysDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NETWORK NAME] [KEY NAME]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete a key",
|
||||
Long: `Delete a key`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.DeleteKey(args[0], args[1])
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(keysDeleteCmd)
|
||||
}
|
20
cli/cmd/keys/list.go
Normal file
20
cli/cmd/keys/list.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var keysListCmd = &cobra.Command{
|
||||
Use: "list [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "List all keys associated with a network",
|
||||
Long: `List all keys associated with a network`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetKeys(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(keysListCmd)
|
||||
}
|
38
cli/cmd/keys/root.go
Normal file
38
cli/cmd/keys/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Manage access keys associated with a network",
|
||||
Long: `Manage access keys associated with a network`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
22
cli/cmd/logs.go
Normal file
22
cli/cmd/logs.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var getLogsCmd = &cobra.Command{
|
||||
Use: "logs",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Retrieve server logs",
|
||||
Long: `Retrieve server logs`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(functions.GetLogs())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(getLogsCmd)
|
||||
}
|
20
cli/cmd/metrics/all.go
Normal file
20
cli/cmd/metrics/all.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var metricsAllCmd = &cobra.Command{
|
||||
Use: "all",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Retrieve all metrics",
|
||||
Long: `Retrieve all metrics`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetAllMetrics())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(metricsAllCmd)
|
||||
}
|
20
cli/cmd/metrics/network.go
Normal file
20
cli/cmd/metrics/network.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var metricsNetworkCmd = &cobra.Command{
|
||||
Use: "network [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Retrieve network metrics",
|
||||
Long: `Retrieve network metrics`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetNetworkNodeMetrics(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(metricsNetworkCmd)
|
||||
}
|
20
cli/cmd/metrics/network_ext.go
Normal file
20
cli/cmd/metrics/network_ext.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var metricsNetworkExtCmd = &cobra.Command{
|
||||
Use: "network_ext [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Retrieve metrics of external clients on a given network",
|
||||
Long: `Retrieve metrics of external clients on a given network`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetNetworkExtMetrics(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(metricsNetworkExtCmd)
|
||||
}
|
20
cli/cmd/metrics/node.go
Normal file
20
cli/cmd/metrics/node.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var metricsNodeCmd = &cobra.Command{
|
||||
Use: "node [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Retrieve node metrics",
|
||||
Long: `Retrieve node metrics`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetNodeMetrics(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(metricsNodeCmd)
|
||||
}
|
38
cli/cmd/metrics/root.go
Normal file
38
cli/cmd/metrics/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "metrics",
|
||||
Short: "Fetch metrics of nodes/networks",
|
||||
Long: `Fetch metrics of nodes/networks`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
85
cli/cmd/network/create.go
Normal file
85
cli/cmd/network/create.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a Network",
|
||||
Long: `Create a Network`,
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
network := &models.Network{}
|
||||
if networkDefinitionFilePath != "" {
|
||||
content, err := os.ReadFile(networkDefinitionFilePath)
|
||||
if err != nil {
|
||||
log.Fatal("Error when opening file: ", err)
|
||||
}
|
||||
if err := json.Unmarshal(content, network); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
network.NetID = netID
|
||||
network.AddressRange = address
|
||||
if address6 != "" {
|
||||
network.AddressRange6 = address6
|
||||
network.IsIPv6 = "yes"
|
||||
}
|
||||
if udpHolePunch {
|
||||
network.DefaultUDPHolePunch = "yes"
|
||||
}
|
||||
if localNetwork {
|
||||
network.IsLocal = "yes"
|
||||
}
|
||||
if defaultACL {
|
||||
network.DefaultACL = "yes"
|
||||
}
|
||||
if pointToSite {
|
||||
network.IsPointToSite = "yes"
|
||||
}
|
||||
network.DefaultInterface = defaultInterface
|
||||
network.DefaultListenPort = int32(defaultListenPort)
|
||||
network.NodeLimit = int32(nodeLimit)
|
||||
network.DefaultPostUp = defaultPostUp
|
||||
network.DefaultPostDown = defaultPostDown
|
||||
network.DefaultKeepalive = int32(defaultKeepalive)
|
||||
if allowManualSignUp {
|
||||
network.AllowManualSignUp = "yes"
|
||||
}
|
||||
network.LocalRange = localRange
|
||||
network.DefaultExtClientDNS = defaultExtClientDNS
|
||||
network.DefaultMTU = int32(defaultMTU)
|
||||
}
|
||||
functions.PrettyPrint(functions.CreateNetwork(network))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkCreateCmd.Flags().StringVar(&networkDefinitionFilePath, "file", "", "Path to network_definition.json")
|
||||
networkCreateCmd.Flags().StringVar(&netID, "name", "", "Name of the network")
|
||||
networkCreateCmd.MarkFlagsMutuallyExclusive("file", "name")
|
||||
networkCreateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 address of the network")
|
||||
networkCreateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 address of the network")
|
||||
networkCreateCmd.Flags().BoolVar(&udpHolePunch, "udp_hole_punch", false, "Enable UDP Hole Punching ?")
|
||||
networkCreateCmd.Flags().BoolVar(&localNetwork, "local", false, "Is the network local (LAN) ?")
|
||||
networkCreateCmd.Flags().BoolVar(&defaultACL, "default_acl", false, "Enable default Access Control List ?")
|
||||
networkCreateCmd.Flags().BoolVar(&pointToSite, "point_to_site", false, "Enforce all clients to have only 1 central peer ?")
|
||||
networkCreateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface")
|
||||
networkCreateCmd.Flags().StringVar(&defaultPostUp, "post_up", "", "Commands to run after server is up `;` separated")
|
||||
networkCreateCmd.Flags().StringVar(&defaultPostDown, "post_down", "", "Commands to run after server is down `;` separated")
|
||||
networkCreateCmd.Flags().StringVar(&localRange, "local_range", "", "Local CIDR range")
|
||||
networkCreateCmd.Flags().StringVar(&defaultExtClientDNS, "ext_client_dns", "", "IPv4 address of DNS server to be used by external clients")
|
||||
networkCreateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 51821, "Default wireguard port each node will attempt to use")
|
||||
networkCreateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be associated with this network")
|
||||
networkCreateCmd.Flags().IntVar(&defaultKeepalive, "keep_alive", 20, "Keep Alive in seconds")
|
||||
networkCreateCmd.Flags().IntVar(&defaultMTU, "mtu", 1280, "MTU size")
|
||||
networkCreateCmd.Flags().BoolVar(&allowManualSignUp, "manual_signup", false, "Allow manual signup ?")
|
||||
rootCmd.AddCommand(networkCreateCmd)
|
||||
}
|
22
cli/cmd/network/delete.go
Normal file
22
cli/cmd/network/delete.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NAME]",
|
||||
Short: "Delete a Network",
|
||||
Long: `Delete a Network`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(*functions.DeleteNetwork(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkDeleteCmd)
|
||||
}
|
22
cli/cmd/network/flags.go
Normal file
22
cli/cmd/network/flags.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package network
|
||||
|
||||
var (
|
||||
networkDefinitionFilePath string
|
||||
netID string
|
||||
address string
|
||||
address6 string
|
||||
udpHolePunch bool
|
||||
localNetwork bool
|
||||
defaultACL bool
|
||||
pointToSite bool
|
||||
defaultInterface string
|
||||
defaultListenPort int
|
||||
nodeLimit int
|
||||
defaultPostUp string
|
||||
defaultPostDown string
|
||||
defaultKeepalive int
|
||||
allowManualSignUp bool
|
||||
localRange string
|
||||
defaultExtClientDNS string
|
||||
defaultMTU int
|
||||
)
|
20
cli/cmd/network/get.go
Normal file
20
cli/cmd/network/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkGetCmd = &cobra.Command{
|
||||
Use: "get [NETWORK NAME]",
|
||||
Short: "Get a Network",
|
||||
Long: `Get a Network`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetNetwork(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkGetCmd)
|
||||
}
|
32
cli/cmd/network/list.go
Normal file
32
cli/cmd/network/list.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all Networks",
|
||||
Long: `List all Networks`,
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
networks := functions.GetNetworks()
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"NetId", "Address Range (IPv4)", "Address Range (IPv6)", "Network Last Modified", "Nodes Last Modified"})
|
||||
for _, n := range *networks {
|
||||
networkLastModified := time.Unix(n.NetworkLastModified, 0).Format(time.RFC3339)
|
||||
nodesLastModified := time.Unix(n.NodesLastModified, 0).Format(time.RFC3339)
|
||||
table.Append([]string{n.NetID, n.AddressRange, n.AddressRange6, networkLastModified, nodesLastModified})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkListCmd)
|
||||
}
|
27
cli/cmd/network/node_limit.go
Normal file
27
cli/cmd/network/node_limit.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkNodeLimitCmd = &cobra.Command{
|
||||
Use: "node_limit [NETWORK NAME] [NEW LIMIT]",
|
||||
Short: "Update network nodel limit",
|
||||
Long: `Update network nodel limit`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
nodelimit, err := strconv.ParseInt(args[1], 10, 32)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
functions.PrettyPrint(functions.UpdateNetworkNodeLimit(args[0], int32(nodelimit)))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkNodeLimitCmd)
|
||||
}
|
20
cli/cmd/network/refresh_keys.go
Normal file
20
cli/cmd/network/refresh_keys.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkRefreshKeysCmd = &cobra.Command{
|
||||
Use: "refresh_keys [NETWORK NAME]",
|
||||
Short: "Refresh public and private key pairs of a network",
|
||||
Long: `Refresh public and private key pairs of a network`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.RefreshKeys(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkRefreshKeysCmd)
|
||||
}
|
40
cli/cmd/network/root.go
Normal file
40
cli/cmd/network/root.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "network",
|
||||
Short: "Manage Netmaker Networks",
|
||||
Long: `Manage Netmaker Networks`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
86
cli/cmd/network/update.go
Normal file
86
cli/cmd/network/update.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkUpdateCmd = &cobra.Command{
|
||||
Use: "update [NETWORK NAME]",
|
||||
Short: "Update a Network",
|
||||
Long: `Update a Network`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
networkName = args[0]
|
||||
network = &models.Network{}
|
||||
)
|
||||
if networkDefinitionFilePath != "" {
|
||||
content, err := os.ReadFile(networkDefinitionFilePath)
|
||||
if err != nil {
|
||||
log.Fatal("Error when opening file: ", err)
|
||||
}
|
||||
if err := json.Unmarshal(content, network); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
network.NetID = networkName
|
||||
network.AddressRange = address
|
||||
if address6 != "" {
|
||||
network.AddressRange6 = address6
|
||||
network.IsIPv6 = "yes"
|
||||
}
|
||||
if udpHolePunch {
|
||||
network.DefaultUDPHolePunch = "yes"
|
||||
}
|
||||
if localNetwork {
|
||||
network.IsLocal = "yes"
|
||||
}
|
||||
if defaultACL {
|
||||
network.DefaultACL = "yes"
|
||||
}
|
||||
if pointToSite {
|
||||
network.IsPointToSite = "yes"
|
||||
}
|
||||
network.DefaultInterface = defaultInterface
|
||||
network.DefaultListenPort = int32(defaultListenPort)
|
||||
network.NodeLimit = int32(nodeLimit)
|
||||
network.DefaultPostUp = defaultPostUp
|
||||
network.DefaultPostDown = defaultPostDown
|
||||
network.DefaultKeepalive = int32(defaultKeepalive)
|
||||
if allowManualSignUp {
|
||||
network.AllowManualSignUp = "yes"
|
||||
}
|
||||
network.LocalRange = localRange
|
||||
network.DefaultExtClientDNS = defaultExtClientDNS
|
||||
network.DefaultMTU = int32(defaultMTU)
|
||||
}
|
||||
functions.PrettyPrint(functions.UpdateNetwork(networkName, network))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkUpdateCmd.Flags().StringVar(&networkDefinitionFilePath, "file", "", "Path to network_definition.json")
|
||||
networkUpdateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 address of the network")
|
||||
networkUpdateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 address of the network")
|
||||
networkUpdateCmd.Flags().BoolVar(&udpHolePunch, "udp_hole_punch", false, "Enable UDP Hole Punching ?")
|
||||
networkUpdateCmd.Flags().BoolVar(&localNetwork, "local", false, "Is the network local (LAN) ?")
|
||||
networkUpdateCmd.Flags().BoolVar(&defaultACL, "default_acl", false, "Enable default Access Control List ?")
|
||||
networkUpdateCmd.Flags().BoolVar(&pointToSite, "point_to_site", false, "Enforce all clients to have only 1 central peer ?")
|
||||
networkUpdateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface")
|
||||
networkUpdateCmd.Flags().StringVar(&defaultPostUp, "post_up", "", "Commands to run after server is up `;` separated")
|
||||
networkUpdateCmd.Flags().StringVar(&defaultPostDown, "post_down", "", "Commands to run after server is down `;` separated")
|
||||
networkUpdateCmd.Flags().StringVar(&localRange, "local_range", "", "Local CIDR range")
|
||||
networkUpdateCmd.Flags().StringVar(&defaultExtClientDNS, "ext_client_dns", "", "IPv4 address of DNS server to be used by external clients")
|
||||
networkUpdateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 0, "Default wireguard port each node will attempt to use")
|
||||
networkUpdateCmd.Flags().IntVar(&nodeLimit, "node_limit", 0, "Maximum number of nodes that can be associated with this network")
|
||||
networkUpdateCmd.Flags().IntVar(&defaultKeepalive, "keep_alive", 0, "Keep Alive in seconds")
|
||||
networkUpdateCmd.Flags().IntVar(&defaultMTU, "mtu", 0, "MTU size")
|
||||
networkUpdateCmd.Flags().BoolVar(&allowManualSignUp, "manual_signup", false, "Allow manual signup ?")
|
||||
rootCmd.AddCommand(networkUpdateCmd)
|
||||
}
|
43
cli/cmd/network_user/create.go
Normal file
43
cli/cmd/network_user/create.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models/promodels"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkuserCreateCmd = &cobra.Command{
|
||||
Use: "create [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Create a network user",
|
||||
Long: `Create a network user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
user := &promodels.NetworkUser{
|
||||
AccessLevel: accessLevel,
|
||||
ClientLimit: clientLimit,
|
||||
NodeLimit: nodeLimit, ID: promodels.NetworkUserID(id),
|
||||
}
|
||||
if clients != "" {
|
||||
user.Clients = strings.Split(clients, ",")
|
||||
}
|
||||
if nodes != "" {
|
||||
user.Nodes = strings.Split(nodes, ",")
|
||||
}
|
||||
functions.CreateNetworkUser(args[0], user)
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkuserCreateCmd.Flags().IntVar(&accessLevel, "access_level", 0, "Custom access level")
|
||||
networkuserCreateCmd.Flags().IntVar(&clientLimit, "client_limit", 0, "Maximum number of external clients that can be created")
|
||||
networkuserCreateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be attached to a network")
|
||||
networkuserCreateCmd.Flags().StringVar(&clients, "clients", "", "Access to list of external clients (comma separated)")
|
||||
networkuserCreateCmd.Flags().StringVar(&nodes, "nodes", "", "Access to list of nodes (comma separated)")
|
||||
networkuserCreateCmd.Flags().StringVar(&id, "id", "", "ID of the network user")
|
||||
networkuserCreateCmd.MarkFlagRequired("id")
|
||||
rootCmd.AddCommand(networkuserCreateCmd)
|
||||
}
|
23
cli/cmd/network_user/delete.go
Normal file
23
cli/cmd/network_user/delete.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkuserDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NETWORK NAME] [NETWORK USER NAME]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete a network user",
|
||||
Long: `Delete a network user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.DeleteNetworkUser(args[0], args[1])
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(networkuserDeleteCmd)
|
||||
}
|
10
cli/cmd/network_user/flags.go
Normal file
10
cli/cmd/network_user/flags.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package network_user
|
||||
|
||||
var (
|
||||
accessLevel int
|
||||
clientLimit int
|
||||
nodeLimit int
|
||||
clients string
|
||||
nodes string
|
||||
id string
|
||||
)
|
27
cli/cmd/network_user/get.go
Normal file
27
cli/cmd/network_user/get.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var data bool
|
||||
|
||||
var networkuserGetCmd = &cobra.Command{
|
||||
Use: "get [NETWORK NAME] [NETWORK USER NAME]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Fetch a network user",
|
||||
Long: `Fetch a network user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if data {
|
||||
functions.PrettyPrint(functions.GetNetworkUserData(args[1]))
|
||||
} else {
|
||||
functions.PrettyPrint(functions.GetNetworkUser(args[0], args[1]))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkuserGetCmd.Flags().BoolVar(&data, "data", false, "Fetch entire data of a network user")
|
||||
rootCmd.AddCommand(networkuserGetCmd)
|
||||
}
|
27
cli/cmd/network_user/list.go
Normal file
27
cli/cmd/network_user/list.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkName string
|
||||
|
||||
var networkuserListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List network users",
|
||||
Long: `List network users`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if networkName != "" {
|
||||
functions.PrettyPrint(functions.GetNetworkUsers(networkName))
|
||||
} else {
|
||||
functions.PrettyPrint(functions.GetAllNetworkUsers())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkuserListCmd.Flags().StringVar(&networkName, "network", "", "Name of the network")
|
||||
rootCmd.AddCommand(networkuserListCmd)
|
||||
}
|
38
cli/cmd/network_user/root.go
Normal file
38
cli/cmd/network_user/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "network_user",
|
||||
Short: "Manage Network Users",
|
||||
Long: `Manage Network Users`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
43
cli/cmd/network_user/update.go
Normal file
43
cli/cmd/network_user/update.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package network_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models/promodels"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var networkuserUpdateCmd = &cobra.Command{
|
||||
Use: "update [NETWORK NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Update a network user",
|
||||
Long: `Update a network user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
user := &promodels.NetworkUser{
|
||||
AccessLevel: accessLevel,
|
||||
ClientLimit: clientLimit,
|
||||
NodeLimit: nodeLimit, ID: promodels.NetworkUserID(id),
|
||||
}
|
||||
if clients != "" {
|
||||
user.Clients = strings.Split(clients, ",")
|
||||
}
|
||||
if nodes != "" {
|
||||
user.Nodes = strings.Split(nodes, ",")
|
||||
}
|
||||
functions.UpdateNetworkUser(args[0], user)
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
networkuserUpdateCmd.Flags().IntVar(&accessLevel, "access_level", 0, "Custom access level")
|
||||
networkuserUpdateCmd.Flags().IntVar(&clientLimit, "client_limit", 0, "Maximum number of external clients that can be created")
|
||||
networkuserUpdateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be attached to a network")
|
||||
networkuserUpdateCmd.Flags().StringVar(&clients, "clients", "", "Access to list of external clients (comma separated)")
|
||||
networkuserUpdateCmd.Flags().StringVar(&nodes, "nodes", "", "Access to list of nodes (comma separated)")
|
||||
networkuserUpdateCmd.Flags().StringVar(&id, "id", "", "ID of the network user")
|
||||
networkuserUpdateCmd.MarkFlagRequired("id")
|
||||
rootCmd.AddCommand(networkuserUpdateCmd)
|
||||
}
|
34
cli/cmd/node/create_egress.go
Normal file
34
cli/cmd/node/create_egress.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeCreateEgressCmd = &cobra.Command{
|
||||
Use: "create_egress [NETWORK NAME] [NODE ID] [EGRESS GATEWAY ADDRESSES (comma separated)]",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Short: "Turn a Node into a Egress",
|
||||
Long: `Turn a Node into a Egress`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
egress := &models.EgressGatewayRequest{
|
||||
NetID: args[0],
|
||||
NodeID: args[1],
|
||||
Interface: networkInterface,
|
||||
Ranges: strings.Split(args[2], ","),
|
||||
}
|
||||
if natEnabled {
|
||||
egress.NatEnabled = "yes"
|
||||
}
|
||||
functions.PrettyPrint(functions.CreateEgress(args[0], args[1], egress))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeCreateEgressCmd.Flags().StringVar(&networkInterface, "interface", "", "Network interface name (ex:- eth0)")
|
||||
nodeCreateEgressCmd.Flags().BoolVar(&natEnabled, "nat", false, "Enable NAT for Egress Traffic ?")
|
||||
rootCmd.AddCommand(nodeCreateEgressCmd)
|
||||
}
|
21
cli/cmd/node/create_ingress.go
Normal file
21
cli/cmd/node/create_ingress.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeCreateIngressCmd = &cobra.Command{
|
||||
Use: "create_ingress [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Turn a Node into a Ingress",
|
||||
Long: `Turn a Node into a Ingress`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.CreateIngress(args[0], args[1], failover))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeCreateIngressCmd.Flags().BoolVar(&failover, "failover", false, "Enable FailOver ?")
|
||||
rootCmd.AddCommand(nodeCreateIngressCmd)
|
||||
}
|
22
cli/cmd/node/create_relay.go
Normal file
22
cli/cmd/node/create_relay.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeCreateRelayCmd = &cobra.Command{
|
||||
Use: "create_relay [NETWORK NAME] [NODE ID] [RELAY ADDRESSES (comma separated)]",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Short: "Turn a Node into a Relay",
|
||||
Long: `Turn a Node into a Relay`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.CreateRelay(args[0], args[1], strings.Split(args[2], ",")))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeCreateRelayCmd)
|
||||
}
|
20
cli/cmd/node/delete.go
Normal file
20
cli/cmd/node/delete.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeDeleteCmd = &cobra.Command{
|
||||
Use: "delete [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete a Node",
|
||||
Long: `Delete a Node`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteNode(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeDeleteCmd)
|
||||
}
|
20
cli/cmd/node/delete_egress.go
Normal file
20
cli/cmd/node/delete_egress.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeDeleteEgressCmd = &cobra.Command{
|
||||
Use: "delete_egress [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete Egress role from a Node",
|
||||
Long: `Delete Egress role from a Node`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteEgress(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeDeleteEgressCmd)
|
||||
}
|
20
cli/cmd/node/delete_ingress.go
Normal file
20
cli/cmd/node/delete_ingress.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeDeleteIngressCmd = &cobra.Command{
|
||||
Use: "delete_ingress [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete Ingress role from a Node",
|
||||
Long: `Delete Ingress role from a Node`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteIngress(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeDeleteIngressCmd)
|
||||
}
|
20
cli/cmd/node/delete_relay.go
Normal file
20
cli/cmd/node/delete_relay.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeDeleteRelayCmd = &cobra.Command{
|
||||
Use: "delete_relay [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Delete Relay role from a Node",
|
||||
Long: `Delete Relay role from a Node`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.DeleteRelay(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeDeleteRelayCmd)
|
||||
}
|
28
cli/cmd/node/flags.go
Normal file
28
cli/cmd/node/flags.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package node
|
||||
|
||||
var (
|
||||
networkInterface string
|
||||
natEnabled bool
|
||||
failover bool
|
||||
networkName string
|
||||
nodeDefinitionFilePath string
|
||||
endpoint string
|
||||
listenPort int
|
||||
address string
|
||||
address6 string
|
||||
localAddress string
|
||||
name string
|
||||
postUp string
|
||||
postDown string
|
||||
allowedIPs string
|
||||
keepAlive int
|
||||
relayAddrs string
|
||||
egressGatewayRanges string
|
||||
localRange string
|
||||
mtu int
|
||||
expirationDateTime int
|
||||
defaultACL bool
|
||||
dnsOn bool
|
||||
disconnect bool
|
||||
networkHub bool
|
||||
)
|
20
cli/cmd/node/get.go
Normal file
20
cli/cmd/node/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeGetCmd = &cobra.Command{
|
||||
Use: "get [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Get a node by ID",
|
||||
Long: `Get a node by ID`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetNodeByID(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeGetCmd)
|
||||
}
|
47
cli/cmd/node/list.go
Normal file
47
cli/cmd/node/list.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/guumaster/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// nodeListCmd lists all nodes
|
||||
var nodeListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List all nodes",
|
||||
Long: `List all nodes`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var data []models.Node
|
||||
if networkName != "" {
|
||||
data = *functions.GetNodes(networkName)
|
||||
} else {
|
||||
data = *functions.GetNodes()
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Name", "Addresses", "Version", "Network", "Egress", "Ingress", "Relay", "ID"})
|
||||
for _, d := range data {
|
||||
addresses := ""
|
||||
if d.Address != "" {
|
||||
addresses += d.Address
|
||||
}
|
||||
if d.Address6 != "" {
|
||||
if d.Address != "" {
|
||||
addresses += ", "
|
||||
}
|
||||
addresses += d.Address6
|
||||
}
|
||||
table.Append([]string{d.Name, addresses, d.Version, d.Network, d.IsEgressGateway, d.IsIngressGateway, d.IsRelay, d.ID})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeListCmd.Flags().StringVar(&networkName, "network", "", "Network name specifier")
|
||||
rootCmd.AddCommand(nodeListCmd)
|
||||
}
|
38
cli/cmd/node/root.go
Normal file
38
cli/cmd/node/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "node",
|
||||
Short: "Manage nodes associated with a network",
|
||||
Long: `Manage nodes associated with a network`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
22
cli/cmd/node/uncordon.go
Normal file
22
cli/cmd/node/uncordon.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeUncordonCmd = &cobra.Command{
|
||||
Use: "uncordon [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Get a node by ID",
|
||||
Long: `Get a node by ID`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(*functions.UncordonNode(args[0], args[1]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(nodeUncordonCmd)
|
||||
}
|
100
cli/cmd/node/update.go
Normal file
100
cli/cmd/node/update.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var nodeUpdateCmd = &cobra.Command{
|
||||
Use: "update [NETWORK NAME] [NODE ID]",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Update a Node",
|
||||
Long: `Update a Node`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
node = &models.Node{}
|
||||
networkName = args[0]
|
||||
nodeID = args[1]
|
||||
)
|
||||
if nodeDefinitionFilePath != "" {
|
||||
content, err := os.ReadFile(nodeDefinitionFilePath)
|
||||
if err != nil {
|
||||
log.Fatal("Error when opening file: ", err)
|
||||
}
|
||||
if err := json.Unmarshal(content, node); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
if endpoint != "" {
|
||||
node.Endpoint = endpoint
|
||||
node.IsStatic = "no"
|
||||
}
|
||||
node.ListenPort = int32(listenPort)
|
||||
node.Address = address
|
||||
node.Address6 = address6
|
||||
node.LocalAddress = localAddress
|
||||
node.Name = name
|
||||
node.PostUp = postUp
|
||||
node.PostDown = postDown
|
||||
if allowedIPs != "" {
|
||||
node.AllowedIPs = strings.Split(allowedIPs, ",")
|
||||
}
|
||||
node.PersistentKeepalive = int32(keepAlive)
|
||||
if relayAddrs != "" {
|
||||
node.RelayAddrs = strings.Split(relayAddrs, ",")
|
||||
}
|
||||
if egressGatewayRanges != "" {
|
||||
node.EgressGatewayRanges = strings.Split(egressGatewayRanges, ",")
|
||||
}
|
||||
if localRange != "" {
|
||||
node.LocalRange = localRange
|
||||
node.IsLocal = "yes"
|
||||
}
|
||||
node.MTU = int32(mtu)
|
||||
node.ExpirationDateTime = int64(expirationDateTime)
|
||||
if defaultACL {
|
||||
node.DefaultACL = "yes"
|
||||
}
|
||||
if dnsOn {
|
||||
node.DNSOn = "yes"
|
||||
}
|
||||
if disconnect {
|
||||
node.Connected = "no"
|
||||
}
|
||||
if networkHub {
|
||||
node.IsHub = "yes"
|
||||
}
|
||||
}
|
||||
functions.PrettyPrint(functions.UpdateNode(networkName, nodeID, node))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeUpdateCmd.Flags().StringVar(&nodeDefinitionFilePath, "file", "", "Filepath of updated node definition in JSON")
|
||||
nodeUpdateCmd.Flags().StringVar(&endpoint, "endpoint", "", "Public endpoint of the node")
|
||||
nodeUpdateCmd.Flags().IntVar(&listenPort, "listen_port", 0, "Default wireguard port for the node")
|
||||
nodeUpdateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 address of the node")
|
||||
nodeUpdateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 address of the node")
|
||||
nodeUpdateCmd.Flags().StringVar(&localAddress, "local_addr", "", "Locally reachable address of the node")
|
||||
nodeUpdateCmd.Flags().StringVar(&name, "name", "", "Node name")
|
||||
nodeUpdateCmd.Flags().StringVar(&postUp, "post_up", "", "Commands to run after node is up `;` separated")
|
||||
nodeUpdateCmd.Flags().StringVar(&postDown, "post_down", "", "Commands to run after node is down `;` separated")
|
||||
nodeUpdateCmd.Flags().StringVar(&allowedIPs, "allowed_addrs", "", "Additional private addresses given to the node (comma separated)")
|
||||
nodeUpdateCmd.Flags().IntVar(&keepAlive, "keep_alive", 0, "Interval in which packets are sent to keep connections open with peers")
|
||||
nodeUpdateCmd.Flags().StringVar(&relayAddrs, "relay_addrs", "", "Addresses for relaying connections if node acts as a relay")
|
||||
nodeUpdateCmd.Flags().StringVar(&egressGatewayRanges, "egress_addrs", "", "Addresses for egressing traffic if node acts as an egress")
|
||||
nodeUpdateCmd.Flags().StringVar(&localRange, "local_range", "", "Local range in which the node will look for private addresses to use as an endpoint if `LocalNetwork` is enabled")
|
||||
nodeUpdateCmd.Flags().IntVar(&mtu, "mtu", 0, "MTU size")
|
||||
nodeUpdateCmd.Flags().IntVar(&expirationDateTime, "expiry", 0, "UNIX timestamp after which node will lose access to the network")
|
||||
nodeUpdateCmd.Flags().BoolVar(&defaultACL, "acl", false, "Enable default ACL ?")
|
||||
nodeUpdateCmd.Flags().BoolVar(&dnsOn, "dns", false, "Setup DNS entries for peers locally ?")
|
||||
nodeUpdateCmd.Flags().BoolVar(&disconnect, "disconnect", false, "Disconnect from the network ?")
|
||||
nodeUpdateCmd.Flags().BoolVar(&networkHub, "hub", false, "On a point to site network, this node is the only one which all peers connect to ?")
|
||||
rootCmd.AddCommand(nodeUpdateCmd)
|
||||
}
|
69
cli/cmd/root.go
Normal file
69
cli/cmd/root.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/cmd/acl"
|
||||
"github.com/gravitl/netmaker/cli/cmd/context"
|
||||
"github.com/gravitl/netmaker/cli/cmd/dns"
|
||||
"github.com/gravitl/netmaker/cli/cmd/ext_client"
|
||||
"github.com/gravitl/netmaker/cli/cmd/keys"
|
||||
"github.com/gravitl/netmaker/cli/cmd/metrics"
|
||||
"github.com/gravitl/netmaker/cli/cmd/network"
|
||||
"github.com/gravitl/netmaker/cli/cmd/network_user"
|
||||
"github.com/gravitl/netmaker/cli/cmd/node"
|
||||
"github.com/gravitl/netmaker/cli/cmd/server"
|
||||
"github.com/gravitl/netmaker/cli/cmd/user"
|
||||
"github.com/gravitl/netmaker/cli/cmd/usergroup"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "nmctl",
|
||||
Short: "CLI for interacting with Netmaker Server",
|
||||
Long: `CLI for interacting with Netmaker Server`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root of all subcommands
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.tctl.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
|
||||
// IMP: Bind subcommands here
|
||||
rootCmd.AddCommand(network.GetRoot())
|
||||
rootCmd.AddCommand(context.GetRoot())
|
||||
rootCmd.AddCommand(keys.GetRoot())
|
||||
rootCmd.AddCommand(acl.GetRoot())
|
||||
rootCmd.AddCommand(node.GetRoot())
|
||||
rootCmd.AddCommand(dns.GetRoot())
|
||||
rootCmd.AddCommand(server.GetRoot())
|
||||
rootCmd.AddCommand(ext_client.GetRoot())
|
||||
rootCmd.AddCommand(user.GetRoot())
|
||||
rootCmd.AddCommand(usergroup.GetRoot())
|
||||
rootCmd.AddCommand(metrics.GetRoot())
|
||||
rootCmd.AddCommand(network_user.GetRoot())
|
||||
}
|
20
cli/cmd/server/config.go
Normal file
20
cli/cmd/server/config.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverConfigCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Retrieve server config",
|
||||
Long: `Retrieve server config`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetServerConfig())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverConfigCmd)
|
||||
}
|
22
cli/cmd/server/has_admin.go
Normal file
22
cli/cmd/server/has_admin.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverHasAdminCmd = &cobra.Command{
|
||||
Use: "has_admin",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Check if server has an admin",
|
||||
Long: `Check if server has an admin`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(*functions.HasAdmin())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverHasAdminCmd)
|
||||
}
|
20
cli/cmd/server/health.go
Normal file
20
cli/cmd/server/health.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverHealthCmd = &cobra.Command{
|
||||
Use: "health",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "View server health",
|
||||
Long: `View server health`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetServerHealth())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverHealthCmd)
|
||||
}
|
20
cli/cmd/server/info.go
Normal file
20
cli/cmd/server/info.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverInfoCmd = &cobra.Command{
|
||||
Use: "info",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Retrieve server information",
|
||||
Long: `Retrieve server information`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetServerInfo())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverInfoCmd)
|
||||
}
|
38
cli/cmd/server/root.go
Normal file
38
cli/cmd/server/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Get netmaker server information",
|
||||
Long: `Get netmaker server information`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
37
cli/cmd/user/create.go
Normal file
37
cli/cmd/user/create.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Create a new user",
|
||||
Long: `Create a new user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
user := &models.User{UserName: username, Password: password, IsAdmin: admin}
|
||||
if networks != "" {
|
||||
user.Networks = strings.Split(networks, ",")
|
||||
}
|
||||
if groups != "" {
|
||||
user.Groups = strings.Split(groups, ",")
|
||||
}
|
||||
functions.PrettyPrint(functions.CreateUser(user))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
userCreateCmd.Flags().StringVar(&username, "name", "", "Name of the user")
|
||||
userCreateCmd.Flags().StringVar(&password, "password", "", "Password of the user")
|
||||
userCreateCmd.MarkFlagRequired("name")
|
||||
userCreateCmd.MarkFlagRequired("password")
|
||||
userCreateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ?")
|
||||
userCreateCmd.Flags().StringVar(&networks, "networks", "", "List of networks the user will access to (comma separated)")
|
||||
userCreateCmd.Flags().StringVar(&groups, "groups", "", "List of user groups the user will be part of (comma separated)")
|
||||
rootCmd.AddCommand(userCreateCmd)
|
||||
}
|
20
cli/cmd/user/delete.go
Normal file
20
cli/cmd/user/delete.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userDeleteCmd = &cobra.Command{
|
||||
Use: "delete [USER NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Delete a user",
|
||||
Long: `Delete a user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(*functions.DeleteUser(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(userDeleteCmd)
|
||||
}
|
9
cli/cmd/user/flags.go
Normal file
9
cli/cmd/user/flags.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package user
|
||||
|
||||
var (
|
||||
username string
|
||||
password string
|
||||
admin bool
|
||||
networks string
|
||||
groups string
|
||||
)
|
20
cli/cmd/user/get.go
Normal file
20
cli/cmd/user/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userGetCmd = &cobra.Command{
|
||||
Use: "get [USER NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Get a user",
|
||||
Long: `Get a user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetUser(args[0]))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(userGetCmd)
|
||||
}
|
30
cli/cmd/user/list.go
Normal file
30
cli/cmd/user/list.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/guumaster/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "List all users",
|
||||
Long: `List all users`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Name", "Admin", "Networks", "Groups"})
|
||||
for _, d := range *functions.ListUsers() {
|
||||
table.Append([]string{d.UserName, strconv.FormatBool(d.IsAdmin), strings.Join(d.Networks, ", "), strings.Join(d.Groups, ", ")})
|
||||
}
|
||||
table.Render()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(userListCmd)
|
||||
}
|
38
cli/cmd/user/root.go
Normal file
38
cli/cmd/user/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "Manage users and permissions",
|
||||
Long: `Manage users and permissions`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
35
cli/cmd/user/update.go
Normal file
35
cli/cmd/user/update.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userUpdateCmd = &cobra.Command{
|
||||
Use: "update [USER NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Update a user",
|
||||
Long: `Update a user`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
user := &models.User{UserName: args[0], IsAdmin: admin}
|
||||
if networks != "" {
|
||||
user.Networks = strings.Split(networks, ",")
|
||||
}
|
||||
if groups != "" {
|
||||
user.Groups = strings.Split(groups, ",")
|
||||
} else {
|
||||
user.Groups = []string{"*"}
|
||||
}
|
||||
functions.PrettyPrint(functions.UpdateUser(user))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
userUpdateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ?")
|
||||
userUpdateCmd.Flags().StringVar(&networks, "networks", "", "List of networks the user will access to (comma separated)")
|
||||
userUpdateCmd.Flags().StringVar(&groups, "groups", "", "List of user groups the user will be part of (comma separated)")
|
||||
rootCmd.AddCommand(userUpdateCmd)
|
||||
}
|
23
cli/cmd/usergroup/create.go
Normal file
23
cli/cmd/usergroup/create.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var usergroupCreateCmd = &cobra.Command{
|
||||
Use: "create [GROUP NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Create a usergroup",
|
||||
Long: `Create a usergroup`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.CreateUsergroup(args[0])
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(usergroupCreateCmd)
|
||||
}
|
23
cli/cmd/usergroup/delete.go
Normal file
23
cli/cmd/usergroup/delete.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var usergroupDeleteCmd = &cobra.Command{
|
||||
Use: "delete [GROUP NAME]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Delete a usergroup",
|
||||
Long: `Delete a usergroup`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.DeleteUsergroup(args[0])
|
||||
fmt.Println("Success")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(usergroupDeleteCmd)
|
||||
}
|
20
cli/cmd/usergroup/get.go
Normal file
20
cli/cmd/usergroup/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/cli/functions"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var usergroupGetCmd = &cobra.Command{
|
||||
Use: "get",
|
||||
Args: cobra.NoArgs,
|
||||
Short: "Fetch all usergroups",
|
||||
Long: `Fetch all usergroups`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
functions.PrettyPrint(functions.GetUsergroups())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(usergroupGetCmd)
|
||||
}
|
38
cli/cmd/usergroup/root.go
Normal file
38
cli/cmd/usergroup/root.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "usergroup",
|
||||
Short: "Manage User Groups",
|
||||
Long: `Manage User Groups`,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// GetRoot returns the root subcommand
|
||||
func GetRoot() *cobra.Command {
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
145
cli/config/config.go
Normal file
145
cli/config/config.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Context maintains configuration for interaction with Netmaker API
|
||||
type Context struct {
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
Username string `yaml:"username,omitempty"`
|
||||
Password string `yaml:"password,omitempty"`
|
||||
MasterKey string `yaml:"masterkey,omitempty"`
|
||||
Current bool `yaml:"current,omitempty"`
|
||||
AuthToken string `yaml:"auth_token,omitempty"`
|
||||
SSO bool `yaml:"sso,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
contextMap = map[string]Context{}
|
||||
configFilePath string
|
||||
filename string
|
||||
)
|
||||
|
||||
func createConfigPathIfNotExists() {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
configFilePath = filepath.Join(homeDir, ".netmaker")
|
||||
// create directory if not exists
|
||||
if err := os.MkdirAll(configFilePath, os.ModePerm); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
filename = filepath.Join(configFilePath, "config.yml")
|
||||
// create file if not exists
|
||||
if _, err := os.Stat(filename); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if _, err := os.Create(filename); err != nil {
|
||||
log.Fatalf("Unable to create file filename: %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
content, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading config file: %s", err)
|
||||
}
|
||||
if err := yaml.Unmarshal(content, &contextMap); err != nil {
|
||||
log.Fatalf("Unable to decode YAML into struct: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func saveContext() {
|
||||
bodyBytes, err := yaml.Marshal(&contextMap)
|
||||
if err != nil {
|
||||
log.Fatalf("Error marshalling into YAML %s", err)
|
||||
}
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := file.Write(bodyBytes); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetCurrentContext - returns current set context
|
||||
func GetCurrentContext() (name string, ctx Context) {
|
||||
for n, c := range contextMap {
|
||||
if c.Current {
|
||||
name, ctx = n, c
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Fatalf("No current context set, do so via `netmaker context use <name>`")
|
||||
return
|
||||
}
|
||||
|
||||
// SetCurrentContext - sets a given context as current context
|
||||
func SetCurrentContext(ctxName string) {
|
||||
if _, ok := contextMap[ctxName]; !ok {
|
||||
log.Fatalf("No such context %s", ctxName)
|
||||
}
|
||||
for key, ctx := range contextMap {
|
||||
ctx.Current = key == ctxName
|
||||
contextMap[key] = ctx
|
||||
}
|
||||
saveContext()
|
||||
}
|
||||
|
||||
// SetContext - updates an existing context or creates a new one
|
||||
func SetContext(ctxName string, ctx Context) {
|
||||
if oldCtx, ok := contextMap[ctxName]; ok && oldCtx.Current {
|
||||
ctx.Current = true
|
||||
}
|
||||
contextMap[ctxName] = ctx
|
||||
saveContext()
|
||||
}
|
||||
|
||||
// SetAuthToken - saves the auth token
|
||||
func SetAuthToken(authToken string) {
|
||||
ctxName, _ := GetCurrentContext()
|
||||
if ctx, ok := contextMap[ctxName]; ok {
|
||||
ctx.AuthToken = authToken
|
||||
contextMap[ctxName] = ctx
|
||||
saveContext()
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteContext - deletes a context
|
||||
func DeleteContext(ctxName string) {
|
||||
if _, ok := contextMap[ctxName]; ok {
|
||||
delete(contextMap, ctxName)
|
||||
saveContext()
|
||||
} else {
|
||||
log.Fatalf("No such context %s", ctxName)
|
||||
}
|
||||
}
|
||||
|
||||
// ListAll - lists all contexts
|
||||
func ListAll() {
|
||||
for key, ctx := range contextMap {
|
||||
fmt.Print("\n", key, " -> ", ctx.Endpoint)
|
||||
if ctx.Current {
|
||||
fmt.Print(" (current)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
createConfigPathIfNotExists()
|
||||
loadConfig()
|
||||
}
|
18
cli/functions/acl.go
Normal file
18
cli/functions/acl.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitl/netmaker/logic/acls"
|
||||
)
|
||||
|
||||
// GetACL - fetch all ACLs associated with a network
|
||||
func GetACL(networkName string) *acls.ACLContainer {
|
||||
return request[acls.ACLContainer](http.MethodGet, fmt.Sprintf("/api/networks/%s/acls", networkName), nil)
|
||||
}
|
||||
|
||||
// UpdateACL - update an ACL
|
||||
func UpdateACL(networkName string, payload *acls.ACLContainer) *acls.ACLContainer {
|
||||
return request[acls.ACLContainer](http.MethodPut, fmt.Sprintf("/api/networks/%s/acls", networkName), payload)
|
||||
}
|
43
cli/functions/dns.go
Normal file
43
cli/functions/dns.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
// GetDNS - fetch all DNS entries
|
||||
func GetDNS() *[]models.DNSEntry {
|
||||
return request[[]models.DNSEntry](http.MethodGet, "/api/dns", nil)
|
||||
}
|
||||
|
||||
// GetNodeDNS - fetch all Node DNS entires
|
||||
func GetNodeDNS(networkName string) *[]models.DNSEntry {
|
||||
return request[[]models.DNSEntry](http.MethodGet, fmt.Sprintf("/api/dns/adm/%s/nodes", networkName), nil)
|
||||
}
|
||||
|
||||
// GetCustomDNS - fetch user defined DNS entriees
|
||||
func GetCustomDNS(networkName string) *[]models.DNSEntry {
|
||||
return request[[]models.DNSEntry](http.MethodGet, fmt.Sprintf("/api/dns/adm/%s/custom", networkName), nil)
|
||||
}
|
||||
|
||||
// GetNetworkDNS - fetch DNS entries associated with a network
|
||||
func GetNetworkDNS(networkName string) *[]models.DNSEntry {
|
||||
return request[[]models.DNSEntry](http.MethodGet, "/api/dns/adm/"+networkName, nil)
|
||||
}
|
||||
|
||||
// CreateDNS - create a DNS entry
|
||||
func CreateDNS(networkName string, payload *models.DNSEntry) *models.DNSEntry {
|
||||
return request[models.DNSEntry](http.MethodPost, "/api/dns/"+networkName, payload)
|
||||
}
|
||||
|
||||
// PushDNS - push a DNS entry to CoreDNS
|
||||
func PushDNS() *string {
|
||||
return request[string](http.MethodPost, "/api/dns/adm/pushdns", nil)
|
||||
}
|
||||
|
||||
// DeleteDNS - delete a DNS entry
|
||||
func DeleteDNS(networkName, domainName string) *string {
|
||||
return request[string](http.MethodDelete, fmt.Sprintf("/api/dns/%s/%s", networkName, domainName), nil)
|
||||
}
|
49
cli/functions/ext_client.go
Normal file
49
cli/functions/ext_client.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
// GetAllExtClients - fetch all external clients
|
||||
func GetAllExtClients() *[]models.ExtClient {
|
||||
return request[[]models.ExtClient](http.MethodGet, "/api/extclients", nil)
|
||||
}
|
||||
|
||||
// GetNetworkExtClients - fetch external clients associated with a network
|
||||
func GetNetworkExtClients(networkName string) *[]models.ExtClient {
|
||||
return request[[]models.ExtClient](http.MethodGet, "/api/extclients/"+networkName, nil)
|
||||
}
|
||||
|
||||
// GetExtClient - fetch a single external client
|
||||
func GetExtClient(networkName, clientID string) *models.ExtClient {
|
||||
return request[models.ExtClient](http.MethodGet, fmt.Sprintf("/api/extclients/%s/%s", networkName, clientID), nil)
|
||||
}
|
||||
|
||||
// GetExtClientConfig - fetch a wireguard config of an external client
|
||||
func GetExtClientConfig(networkName, clientID string) string {
|
||||
return get(fmt.Sprintf("/api/extclients/%s/%s/file", networkName, clientID))
|
||||
}
|
||||
|
||||
// CreateExtClient - create an external client
|
||||
func CreateExtClient(networkName, nodeID, extClientID string) {
|
||||
if extClientID != "" {
|
||||
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), &models.CustomExtClient{
|
||||
ClientID: extClientID,
|
||||
})
|
||||
} else {
|
||||
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), nil)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteExtClient - delete an external client
|
||||
func DeleteExtClient(networkName, clientID string) *models.SuccessResponse {
|
||||
return request[models.SuccessResponse](http.MethodDelete, fmt.Sprintf("/api/extclients/%s/%s", networkName, clientID), nil)
|
||||
}
|
||||
|
||||
// UpdateExtClient - update an external client
|
||||
func UpdateExtClient(networkName, clientID string, payload *models.ExtClient) *models.ExtClient {
|
||||
return request[models.ExtClient](http.MethodPut, fmt.Sprintf("/api/extclients/%s/%s", networkName, clientID), payload)
|
||||
}
|
189
cli/functions/http_client.go
Normal file
189
cli/functions/http_client.go
Normal file
@@ -0,0 +1,189 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/gravitl/netmaker/cli/config"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
func ssoLogin(endpoint string) string {
|
||||
var (
|
||||
authToken string
|
||||
interrupt = make(chan os.Signal, 1)
|
||||
url, _ = url.Parse(endpoint)
|
||||
socketURL = fmt.Sprintf("wss://%s/api/oauth/headless", url.Host)
|
||||
)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
conn, _, err := websocket.DefaultDialer.Dial(socketURL, nil)
|
||||
if err != nil {
|
||||
log.Fatal("error connecting to endpoint ", socketURL, err.Error())
|
||||
}
|
||||
defer conn.Close()
|
||||
_, msg, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Fatal("error reading from server: ", err.Error())
|
||||
}
|
||||
fmt.Printf("Please visit:\n %s \n to authenticate\n", string(msg))
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
go func() {
|
||||
for {
|
||||
msgType, msg, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
if msgType < 0 {
|
||||
done <- struct{}{}
|
||||
return
|
||||
}
|
||||
if !strings.Contains(err.Error(), "normal") {
|
||||
log.Fatal("read error: ", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
if msgType == websocket.CloseMessage {
|
||||
done <- struct{}{}
|
||||
return
|
||||
}
|
||||
if strings.Contains(string(msg), "JWT: ") {
|
||||
authToken = strings.TrimPrefix(string(msg), "JWT: ")
|
||||
} else {
|
||||
logger.Log(0, "Message from server:", string(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return authToken
|
||||
case <-interrupt:
|
||||
err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
if err != nil {
|
||||
logger.Log(0, "write close:", err.Error())
|
||||
}
|
||||
return authToken
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getAuthToken(ctx config.Context, force bool) string {
|
||||
if !force && ctx.AuthToken != "" {
|
||||
return ctx.AuthToken
|
||||
}
|
||||
if ctx.SSO {
|
||||
authToken := ssoLogin(ctx.Endpoint)
|
||||
config.SetAuthToken(authToken)
|
||||
return authToken
|
||||
}
|
||||
authParams := &models.UserAuthParams{UserName: ctx.Username, Password: ctx.Password}
|
||||
payload, err := json.Marshal(authParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
res, err := http.Post(ctx.Endpoint+"/api/users/adm/authenticate", "application/json", bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
resBodyBytes, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("Client could not read response body: %s", err)
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
log.Fatalf("Error Status: %d Response: %s", res.StatusCode, string(resBodyBytes))
|
||||
}
|
||||
body := new(models.SuccessResponse)
|
||||
if err := json.Unmarshal(resBodyBytes, body); err != nil {
|
||||
log.Fatalf("Error unmarshalling JSON: %s", err)
|
||||
}
|
||||
authToken := body.Response.(map[string]any)["AuthToken"].(string)
|
||||
config.SetAuthToken(authToken)
|
||||
return authToken
|
||||
}
|
||||
|
||||
func request[T any](method, route string, payload any) *T {
|
||||
var (
|
||||
_, ctx = config.GetCurrentContext()
|
||||
req *http.Request
|
||||
err error
|
||||
)
|
||||
if payload == nil {
|
||||
req, err = http.NewRequest(method, ctx.Endpoint+route, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Client could not create request: %s", err)
|
||||
}
|
||||
} else {
|
||||
payloadBytes, jsonErr := json.Marshal(payload)
|
||||
if jsonErr != nil {
|
||||
log.Fatalf("Error in request JSON marshalling: %s", err)
|
||||
}
|
||||
req, err = http.NewRequest(method, ctx.Endpoint+route, bytes.NewReader(payloadBytes))
|
||||
if err != nil {
|
||||
log.Fatalf("Client could not create request: %s", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
if ctx.MasterKey != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+ctx.MasterKey)
|
||||
} else {
|
||||
req.Header.Set("Authorization", "Bearer "+getAuthToken(ctx, false))
|
||||
}
|
||||
retried := false
|
||||
retry:
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf("Client error making http request: %s", err)
|
||||
}
|
||||
// refresh JWT token
|
||||
if res.StatusCode == http.StatusUnauthorized && !retried && ctx.MasterKey == "" {
|
||||
req.Header.Set("Authorization", "Bearer "+getAuthToken(ctx, true))
|
||||
retried = true
|
||||
goto retry
|
||||
}
|
||||
resBodyBytes, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("Client could not read response body: %s", err)
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
log.Fatalf("Error Status: %d Response: %s", res.StatusCode, string(resBodyBytes))
|
||||
}
|
||||
body := new(T)
|
||||
if len(resBodyBytes) > 0 {
|
||||
if err := json.Unmarshal(resBodyBytes, body); err != nil {
|
||||
log.Fatalf("Error unmarshalling JSON: %s", err)
|
||||
}
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
func get(route string) string {
|
||||
_, ctx := config.GetCurrentContext()
|
||||
req, err := http.NewRequest(http.MethodGet, ctx.Endpoint+route, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if ctx.MasterKey != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+ctx.MasterKey)
|
||||
} else {
|
||||
req.Header.Set("Authorization", "Bearer "+getAuthToken(ctx, true))
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
bodyBytes, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return string(bodyBytes)
|
||||
}
|
23
cli/functions/keys.go
Normal file
23
cli/functions/keys.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
// GetKeys - fetch all access keys of a network
|
||||
func GetKeys(networkName string) *[]models.AccessKey {
|
||||
return request[[]models.AccessKey](http.MethodGet, fmt.Sprintf("/api/networks/%s/keys", networkName), nil)
|
||||
}
|
||||
|
||||
// CreateKey - create an access key
|
||||
func CreateKey(networkName string, key *models.AccessKey) *models.AccessKey {
|
||||
return request[models.AccessKey](http.MethodPost, fmt.Sprintf("/api/networks/%s/keys", networkName), key)
|
||||
}
|
||||
|
||||
// DeleteKey - delete an access key
|
||||
func DeleteKey(networkName, keyName string) {
|
||||
request[string](http.MethodDelete, fmt.Sprintf("/api/networks/%s/keys/%s", networkName, keyName), nil)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user