mirror of
https://github.com/netbirdio/netbird.git
synced 2026-03-31 06:34:14 -04:00
[management, reverse proxy] Add reverse proxy feature (#5291)
* implement reverse proxy --------- Co-authored-by: Alisdair MacLeod <git@alisdairmacleod.co.uk> Co-authored-by: mlsmaycon <mlsmaycon@gmail.com> Co-authored-by: Eduard Gert <kontakt@eduardgert.de> Co-authored-by: Viktor Liu <viktor@netbird.io> Co-authored-by: Diego Noguês <diego.sure@gmail.com> Co-authored-by: Diego Noguês <49420+diegocn@users.noreply.github.com> Co-authored-by: Bethuel Mmbaga <bethuelmbaga12@gmail.com> Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com> Co-authored-by: Ashley Mensah <ashleyamo982@gmail.com>
This commit is contained in:
136
shared/hash/argon2id/argon2id.go
Normal file
136
shared/hash/argon2id/argon2id.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package argon2id
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
|
||||
const (
|
||||
argon2Memory = 19456
|
||||
argon2Iterations = 2
|
||||
argon2Parallelism = 1
|
||||
argon2SaltLength = 16
|
||||
argon2KeyLength = 32
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidHash is returned when the hash string format is invalid
|
||||
ErrInvalidHash = errors.New("invalid hash format")
|
||||
|
||||
// ErrIncompatibleVersion is returned when the Argon2 version is not supported
|
||||
ErrIncompatibleVersion = errors.New("incompatible argon2 version")
|
||||
|
||||
// ErrMismatchedHashAndPassword is returned when password verification fails
|
||||
ErrMismatchedHashAndPassword = errors.New("password does not match hash")
|
||||
)
|
||||
|
||||
func Hash(secret string) (string, error) {
|
||||
salt := make([]byte, argon2SaltLength)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
return "", fmt.Errorf("failed to generate salt: %w", err)
|
||||
}
|
||||
|
||||
hash := argon2.IDKey(
|
||||
[]byte(secret),
|
||||
salt,
|
||||
argon2Iterations,
|
||||
argon2Memory,
|
||||
argon2Parallelism,
|
||||
argon2KeyLength,
|
||||
)
|
||||
|
||||
encodedSalt := base64.RawStdEncoding.EncodeToString(salt)
|
||||
encodedHash := base64.RawStdEncoding.EncodeToString(hash)
|
||||
|
||||
return fmt.Sprintf(
|
||||
"$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
|
||||
argon2.Version,
|
||||
argon2Memory,
|
||||
argon2Iterations,
|
||||
argon2Parallelism,
|
||||
encodedSalt,
|
||||
encodedHash,
|
||||
), nil
|
||||
}
|
||||
|
||||
func Verify(secret, encodedHash string) error {
|
||||
params, salt, hash, err := decodeHash(encodedHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
computedHash := argon2.IDKey(
|
||||
[]byte(secret),
|
||||
salt,
|
||||
params.iterations,
|
||||
params.memory,
|
||||
params.parallelism,
|
||||
params.keyLength,
|
||||
)
|
||||
|
||||
if subtle.ConstantTimeCompare(hash, computedHash) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrMismatchedHashAndPassword
|
||||
}
|
||||
|
||||
type hashParams struct {
|
||||
memory uint32
|
||||
iterations uint32
|
||||
parallelism uint8
|
||||
keyLength uint32
|
||||
version int
|
||||
}
|
||||
|
||||
func decodeHash(encodedHash string) (*hashParams, []byte, []byte, error) {
|
||||
parts := strings.Split(encodedHash, "$")
|
||||
|
||||
if len(parts) != 6 {
|
||||
return nil, nil, nil, ErrInvalidHash
|
||||
}
|
||||
|
||||
if parts[1] != "argon2id" {
|
||||
return nil, nil, nil, ErrInvalidHash
|
||||
}
|
||||
|
||||
var version int
|
||||
if _, err := fmt.Sscanf(parts[2], "v=%d", &version); err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("%w: invalid version: %v", ErrInvalidHash, err)
|
||||
}
|
||||
if version != argon2.Version {
|
||||
return nil, nil, nil, ErrIncompatibleVersion
|
||||
}
|
||||
|
||||
var memory, iterations uint32
|
||||
var parallelism uint8
|
||||
if _, err := fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &memory, &iterations, ¶llelism); err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("%w: invalid parameters: %v", ErrInvalidHash, err)
|
||||
}
|
||||
|
||||
salt, err := base64.RawStdEncoding.DecodeString(parts[4])
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("%w: invalid salt encoding: %v", ErrInvalidHash, err)
|
||||
}
|
||||
|
||||
hash, err := base64.RawStdEncoding.DecodeString(parts[5])
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("%w: invalid hash encoding: %v", ErrInvalidHash, err)
|
||||
}
|
||||
|
||||
params := &hashParams{
|
||||
memory: memory,
|
||||
iterations: iterations,
|
||||
parallelism: parallelism,
|
||||
keyLength: uint32(len(hash)),
|
||||
version: version,
|
||||
}
|
||||
|
||||
return params, salt, hash, nil
|
||||
}
|
||||
327
shared/hash/argon2id/argon2id_test.go
Normal file
327
shared/hash/argon2id/argon2id_test.go
Normal file
@@ -0,0 +1,327 @@
|
||||
package argon2id
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
secret string
|
||||
}{
|
||||
{
|
||||
name: "simple password",
|
||||
secret: "password123",
|
||||
},
|
||||
{
|
||||
name: "complex password with special chars",
|
||||
secret: "P@ssw0rd!#$%^&*()",
|
||||
},
|
||||
{
|
||||
name: "long password",
|
||||
secret: strings.Repeat("a", 100),
|
||||
},
|
||||
{
|
||||
name: "empty password",
|
||||
secret: "",
|
||||
},
|
||||
{
|
||||
name: "unicode password",
|
||||
secret: "пароль密码🔐",
|
||||
},
|
||||
{
|
||||
name: "numeric PIN",
|
||||
secret: "123456",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hash, err := Hash(tt.secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
// Verify hash format
|
||||
if !strings.HasPrefix(hash, "$argon2id$") {
|
||||
t.Errorf("Hash() = %v, want hash starting with $argon2id$", hash)
|
||||
}
|
||||
|
||||
// Verify hash has correct number of components
|
||||
parts := strings.Split(hash, "$")
|
||||
if len(parts) != 6 {
|
||||
t.Errorf("Hash() has %d parts, want 6", len(parts))
|
||||
}
|
||||
|
||||
// Verify version is present
|
||||
if !strings.HasPrefix(hash, "$argon2id$v=") {
|
||||
t.Errorf("Hash() missing version, got %v", hash)
|
||||
}
|
||||
|
||||
// Verify each hash is unique (different salt)
|
||||
hash2, err := Hash(tt.secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() second call error = %v", err)
|
||||
}
|
||||
if hash == hash2 {
|
||||
t.Error("Hash() produces identical hashes for same input (salt not random)")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerify(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
secret string
|
||||
wantError error
|
||||
}{
|
||||
{
|
||||
name: "valid password",
|
||||
secret: "correctPassword",
|
||||
wantError: nil,
|
||||
},
|
||||
{
|
||||
name: "valid PIN",
|
||||
secret: "1234",
|
||||
wantError: nil,
|
||||
},
|
||||
{
|
||||
name: "empty secret",
|
||||
secret: "",
|
||||
wantError: nil,
|
||||
},
|
||||
{
|
||||
name: "unicode secret",
|
||||
secret: "密码🔐",
|
||||
wantError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Generate hash
|
||||
hash, err := Hash(tt.secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
// Verify correct secret
|
||||
err = Verify(tt.secret, hash)
|
||||
if !errors.Is(err, tt.wantError) {
|
||||
t.Errorf("Verify() error = %v, wantError %v", err, tt.wantError)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyIncorrectPassword(t *testing.T) {
|
||||
secret := "correctPassword"
|
||||
wrongSecret := "wrongPassword"
|
||||
|
||||
hash, err := Hash(secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
err = Verify(wrongSecret, hash)
|
||||
if !errors.Is(err, ErrMismatchedHashAndPassword) {
|
||||
t.Errorf("Verify() error = %v, want %v", err, ErrMismatchedHashAndPassword)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyInvalidHashFormat(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
invalidHash string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "empty hash",
|
||||
invalidHash: "",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "wrong algorithm",
|
||||
invalidHash: "$bcrypt$v=19$m=19456,t=2,p=1$c2FsdA$aGFzaA",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "missing parts",
|
||||
invalidHash: "$argon2id$v=19$m=19456",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "too many parts",
|
||||
invalidHash: "$argon2id$v=19$m=19456,t=2,p=1$salt$hash$extra",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "invalid version format",
|
||||
invalidHash: "$argon2id$vXX$m=19456,t=2,p=1$c2FsdA$aGFzaA",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "invalid parameters format",
|
||||
invalidHash: "$argon2id$v=19$mXX,tYY,pZZ$c2FsdA$aGFzaA",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "invalid salt base64",
|
||||
invalidHash: "$argon2id$v=19$m=19456,t=2,p=1$not-valid-base64!@#$aGFzaA",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
{
|
||||
name: "invalid hash base64",
|
||||
invalidHash: "$argon2id$v=19$m=19456,t=2,p=1$c2FsdA$not-valid-base64!@#",
|
||||
expectedError: ErrInvalidHash,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := Verify("password", tt.invalidHash)
|
||||
if err == nil {
|
||||
t.Errorf("Verify() expected error, got nil")
|
||||
return
|
||||
}
|
||||
|
||||
if !errors.Is(err, tt.expectedError) && !strings.Contains(err.Error(), tt.expectedError.Error()) {
|
||||
t.Errorf("Verify() error = %v, want error containing %v", err, tt.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyIncompatibleVersion(t *testing.T) {
|
||||
// Manually craft a hash with wrong version
|
||||
invalidVersionHash := "$argon2id$v=18$m=19456,t=2,p=1$c2FsdDEyMzQ1Njc4OTA$aGFzaDEyMzQ1Njc4OTBhYmNkZWZnaGlqa2xtbm9w"
|
||||
|
||||
err := Verify("password", invalidVersionHash)
|
||||
if !errors.Is(err, ErrIncompatibleVersion) {
|
||||
t.Errorf("Verify() error = %v, want %v", err, ErrIncompatibleVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashDeterminism(t *testing.T) {
|
||||
// Ensure different hashes for same password (random salt)
|
||||
password := "testPassword"
|
||||
hashes := make(map[string]bool)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
hash, err := Hash(password)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
if hashes[hash] {
|
||||
t.Error("Hash() produced duplicate hash (salt generation may be broken)")
|
||||
}
|
||||
hashes[hash] = true
|
||||
}
|
||||
|
||||
if len(hashes) != 10 {
|
||||
t.Errorf("Expected 10 unique hashes, got %d", len(hashes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOWASPCompliance(t *testing.T) {
|
||||
// Test that generated hashes use OWASP-recommended parameters
|
||||
secret := "testPassword"
|
||||
hash, err := Hash(secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
params, _, _, err := decodeHash(hash)
|
||||
if err != nil {
|
||||
t.Fatalf("decodeHash() error = %v", err)
|
||||
}
|
||||
|
||||
// Verify OWASP minimum baseline parameters
|
||||
if params.memory != 19456 {
|
||||
t.Errorf("memory = %d, want 19456 (OWASP baseline)", params.memory)
|
||||
}
|
||||
if params.iterations != 2 {
|
||||
t.Errorf("iterations = %d, want 2 (OWASP baseline)", params.iterations)
|
||||
}
|
||||
if params.parallelism != 1 {
|
||||
t.Errorf("parallelism = %d, want 1 (OWASP baseline)", params.parallelism)
|
||||
}
|
||||
if params.keyLength != 32 {
|
||||
t.Errorf("keyLength = %d, want 32", params.keyLength)
|
||||
}
|
||||
if params.version != argon2.Version {
|
||||
t.Errorf("version = %d, want %d", params.version, argon2.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstantTimeComparison(t *testing.T) {
|
||||
// This test verifies that Verify() is using constant-time comparison
|
||||
// by ensuring it doesn't fail differently for similar vs different hashes
|
||||
secret := "password123"
|
||||
wrongSecret := "password124" // One character different
|
||||
|
||||
hash, err := Hash(secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
// Both wrong passwords should return the same error
|
||||
err1 := Verify(wrongSecret, hash)
|
||||
err2 := Verify("completelydifferent", hash)
|
||||
|
||||
if !errors.Is(err1, ErrMismatchedHashAndPassword) {
|
||||
t.Errorf("Verify() error = %v, want %v", err1, ErrMismatchedHashAndPassword)
|
||||
}
|
||||
if !errors.Is(err2, ErrMismatchedHashAndPassword) {
|
||||
t.Errorf("Verify() error = %v, want %v", err2, ErrMismatchedHashAndPassword)
|
||||
}
|
||||
|
||||
// Errors should be identical (same error type and message)
|
||||
if err1.Error() != err2.Error() {
|
||||
t.Error("Verify() returns different errors for different wrong passwords (potential timing attack)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaseSensitivity(t *testing.T) {
|
||||
// Passwords should be case-sensitive
|
||||
secret := "Password123"
|
||||
wrongSecret := "password123"
|
||||
|
||||
hash, err := Hash(secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Hash() error = %v", err)
|
||||
}
|
||||
|
||||
// Correct password should verify
|
||||
if err := Verify(secret, hash); err != nil {
|
||||
t.Errorf("Verify() with correct password error = %v, want nil", err)
|
||||
}
|
||||
|
||||
// Wrong case should not verify
|
||||
if err := Verify(wrongSecret, hash); !errors.Is(err, ErrMismatchedHashAndPassword) {
|
||||
t.Errorf("Verify() with wrong case error = %v, want %v", err, ErrMismatchedHashAndPassword)
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark tests
|
||||
func BenchmarkHash(b *testing.B) {
|
||||
secret := "benchmarkPassword123"
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = Hash(secret)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerify(b *testing.B) {
|
||||
secret := "benchmarkPassword123"
|
||||
hash, _ := Hash(secret)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = Verify(secret, hash)
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ tags:
|
||||
x-cloud-only: true
|
||||
- name: Identity Providers
|
||||
description: Interact with and view information about identity providers.
|
||||
- name: Services
|
||||
description: Interact with and view information about reverse proxy services.
|
||||
- name: Instance
|
||||
description: Instance setup and status endpoints for initial configuration.
|
||||
- name: Jobs
|
||||
@@ -2244,7 +2246,53 @@ components:
|
||||
activity_code:
|
||||
description: The string code of the activity that occurred during the event
|
||||
type: string
|
||||
enum: [ "peer.user.add", "peer.setupkey.add", "user.join", "user.invite", "account.create", "account.delete", "user.peer.delete", "rule.add", "rule.update", "rule.delete", "policy.add", "policy.update", "policy.delete", "setupkey.add", "setupkey.update", "setupkey.revoke", "setupkey.overuse", "setupkey.delete", "group.add", "group.update", "group.delete", "peer.group.add", "peer.group.delete", "user.group.add", "user.group.delete", "user.role.update", "setupkey.group.add", "setupkey.group.delete", "dns.setting.disabled.management.group.add", "dns.setting.disabled.management.group.delete", "route.add", "route.delete", "route.update", "peer.ssh.enable", "peer.ssh.disable", "peer.rename", "peer.login.expiration.enable", "peer.login.expiration.disable", "nameserver.group.add", "nameserver.group.delete", "nameserver.group.update", "account.setting.peer.login.expiration.update", "account.setting.peer.login.expiration.enable", "account.setting.peer.login.expiration.disable", "personal.access.token.create", "personal.access.token.delete", "service.user.create", "service.user.delete", "user.block", "user.unblock", "user.delete", "user.peer.login", "peer.login.expire", "dashboard.login", "integration.create", "integration.update", "integration.delete", "account.setting.peer.approval.enable", "account.setting.peer.approval.disable", "peer.approve", "peer.approval.revoke", "transferred.owner.role", "posture.check.create", "posture.check.update", "posture.check.delete", "peer.inactivity.expiration.enable", "peer.inactivity.expiration.disable", "account.peer.inactivity.expiration.enable", "account.peer.inactivity.expiration.disable", "account.peer.inactivity.expiration.update", "account.setting.group.propagation.enable", "account.setting.group.propagation.disable", "account.setting.routing.peer.dns.resolution.enable", "account.setting.routing.peer.dns.resolution.disable", "network.create", "network.update", "network.delete", "network.resource.create", "network.resource.update", "network.resource.delete", "network.router.create", "network.router.update", "network.router.delete", "resource.group.add", "resource.group.delete", "account.dns.domain.update", "account.setting.lazy.connection.enable", "account.setting.lazy.connection.disable", "account.network.range.update", "peer.ip.update", "user.approve", "user.reject", "user.create", "account.settings.auto.version.update", "identityprovider.create", "identityprovider.update", "identityprovider.delete", "dns.zone.create", "dns.zone.update", "dns.zone.delete", "dns.zone.record.create", "dns.zone.record.update", "dns.zone.record.delete", "peer.job.create", "user.password.change", "user.invite.link.create", "user.invite.link.accept", "user.invite.link.regenerate", "user.invite.link.delete" ]
|
||||
enum: [
|
||||
"peer.user.add", "peer.setupkey.add", "user.join", "user.invite", "account.create", "account.delete",
|
||||
"user.peer.delete", "rule.add", "rule.update", "rule.delete",
|
||||
"policy.add", "policy.update", "policy.delete",
|
||||
"setupkey.add", "setupkey.update", "setupkey.revoke", "setupkey.overuse", "setupkey.delete",
|
||||
"group.add", "group.update", "group.delete",
|
||||
"peer.group.add", "peer.group.delete",
|
||||
"user.group.add", "user.group.delete", "user.role.update",
|
||||
"setupkey.group.add", "setupkey.group.delete",
|
||||
"dns.setting.disabled.management.group.add", "dns.setting.disabled.management.group.delete",
|
||||
"route.add", "route.delete", "route.update",
|
||||
"peer.ssh.enable", "peer.ssh.disable", "peer.rename",
|
||||
"peer.login.expiration.enable", "peer.login.expiration.disable",
|
||||
"nameserver.group.add", "nameserver.group.delete", "nameserver.group.update",
|
||||
"account.setting.peer.login.expiration.update", "account.setting.peer.login.expiration.enable", "account.setting.peer.login.expiration.disable",
|
||||
"personal.access.token.create", "personal.access.token.delete",
|
||||
"service.user.create", "service.user.delete",
|
||||
"user.block", "user.unblock", "user.delete",
|
||||
"user.peer.login", "peer.login.expire",
|
||||
"dashboard.login",
|
||||
"integration.create", "integration.update", "integration.delete",
|
||||
"account.setting.peer.approval.enable", "account.setting.peer.approval.disable",
|
||||
"peer.approve", "peer.approval.revoke",
|
||||
"transferred.owner.role",
|
||||
"posture.check.create", "posture.check.update", "posture.check.delete",
|
||||
"peer.inactivity.expiration.enable", "peer.inactivity.expiration.disable",
|
||||
"account.peer.inactivity.expiration.enable", "account.peer.inactivity.expiration.disable", "account.peer.inactivity.expiration.update",
|
||||
"account.setting.group.propagation.enable", "account.setting.group.propagation.disable",
|
||||
"account.setting.routing.peer.dns.resolution.enable", "account.setting.routing.peer.dns.resolution.disable",
|
||||
"network.create", "network.update", "network.delete",
|
||||
"network.resource.create", "network.resource.update", "network.resource.delete",
|
||||
"network.router.create", "network.router.update", "network.router.delete",
|
||||
"resource.group.add", "resource.group.delete",
|
||||
"account.dns.domain.update",
|
||||
"account.setting.lazy.connection.enable", "account.setting.lazy.connection.disable",
|
||||
"account.network.range.update",
|
||||
"peer.ip.update",
|
||||
"user.approve", "user.reject", "user.create",
|
||||
"account.settings.auto.version.update",
|
||||
"identityprovider.create", "identityprovider.update", "identityprovider.delete",
|
||||
"dns.zone.create", "dns.zone.update", "dns.zone.delete",
|
||||
"dns.zone.record.create", "dns.zone.record.update", "dns.zone.record.delete",
|
||||
"peer.job.create",
|
||||
"user.password.change",
|
||||
"user.invite.link.create", "user.invite.link.accept", "user.invite.link.regenerate", "user.invite.link.delete",
|
||||
"service.create", "service.update", "service.delete"
|
||||
]
|
||||
example: route.add
|
||||
initiator_id:
|
||||
description: The ID of the initiator of the event. E.g., an ID of a user that triggered the event.
|
||||
@@ -2702,6 +2750,105 @@ components:
|
||||
- page_size
|
||||
- total_records
|
||||
- total_pages
|
||||
ProxyAccessLog:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: "Unique identifier for the access log entry"
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
service_id:
|
||||
type: string
|
||||
description: "ID of the service that handled the request"
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
description: "Timestamp when the request was made"
|
||||
example: "2024-01-31T15:30:00Z"
|
||||
method:
|
||||
type: string
|
||||
description: "HTTP method of the request"
|
||||
example: "GET"
|
||||
host:
|
||||
type: string
|
||||
description: "Host header of the request"
|
||||
example: "example.com"
|
||||
path:
|
||||
type: string
|
||||
description: "Path of the request"
|
||||
example: "/api/users"
|
||||
duration_ms:
|
||||
type: integer
|
||||
description: "Duration of the request in milliseconds"
|
||||
example: 150
|
||||
status_code:
|
||||
type: integer
|
||||
description: "HTTP status code returned"
|
||||
example: 200
|
||||
source_ip:
|
||||
type: string
|
||||
description: "Source IP address of the request"
|
||||
example: "192.168.1.100"
|
||||
reason:
|
||||
type: string
|
||||
description: "Reason for the request result (e.g., authentication failure)"
|
||||
example: "Authentication failed"
|
||||
user_id:
|
||||
type: string
|
||||
description: "ID of the authenticated user, if applicable"
|
||||
example: "user-123"
|
||||
auth_method_used:
|
||||
type: string
|
||||
description: "Authentication method used (e.g., password, pin, oidc)"
|
||||
example: "oidc"
|
||||
country_code:
|
||||
type: string
|
||||
description: "Country code from geolocation"
|
||||
example: "US"
|
||||
city_name:
|
||||
type: string
|
||||
description: "City name from geolocation"
|
||||
example: "San Francisco"
|
||||
required:
|
||||
- id
|
||||
- service_id
|
||||
- timestamp
|
||||
- method
|
||||
- host
|
||||
- path
|
||||
- duration_ms
|
||||
- status_code
|
||||
ProxyAccessLogsResponse:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
description: List of proxy access log entries
|
||||
items:
|
||||
$ref: "#/components/schemas/ProxyAccessLog"
|
||||
page:
|
||||
type: integer
|
||||
description: Current page number
|
||||
example: 1
|
||||
page_size:
|
||||
type: integer
|
||||
description: Number of items per page
|
||||
example: 50
|
||||
total_records:
|
||||
type: integer
|
||||
description: Total number of log records available
|
||||
example: 523
|
||||
total_pages:
|
||||
type: integer
|
||||
description: Total number of pages available
|
||||
example: 11
|
||||
required:
|
||||
- data
|
||||
- page
|
||||
- page_size
|
||||
- total_records
|
||||
- total_pages
|
||||
IdentityProviderType:
|
||||
type: string
|
||||
description: Type of identity provider
|
||||
@@ -2767,6 +2914,251 @@ components:
|
||||
- issuer
|
||||
- client_id
|
||||
- client_secret
|
||||
Service:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Service ID
|
||||
name:
|
||||
type: string
|
||||
description: Service name
|
||||
domain:
|
||||
type: string
|
||||
description: Domain for the service
|
||||
proxy_cluster:
|
||||
type: string
|
||||
description: The proxy cluster handling this service (derived from domain)
|
||||
example: "eu.proxy.netbird.io"
|
||||
targets:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ServiceTarget'
|
||||
description: List of target backends for this service
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether the service is enabled
|
||||
pass_host_header:
|
||||
type: boolean
|
||||
description: When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
rewrite_redirects:
|
||||
type: boolean
|
||||
description: When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
auth:
|
||||
$ref: '#/components/schemas/ServiceAuthConfig'
|
||||
meta:
|
||||
$ref: '#/components/schemas/ServiceMeta'
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- domain
|
||||
- targets
|
||||
- enabled
|
||||
- auth
|
||||
- meta
|
||||
ServiceMeta:
|
||||
type: object
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Timestamp when the service was created
|
||||
example: "2024-02-03T10:30:00Z"
|
||||
certificate_issued_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Timestamp when the certificate was issued (empty if not yet issued)
|
||||
example: "2024-02-03T10:35:00Z"
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
- pending
|
||||
- active
|
||||
- tunnel_not_created
|
||||
- certificate_pending
|
||||
- certificate_failed
|
||||
- error
|
||||
description: Current status of the service
|
||||
example: "active"
|
||||
required:
|
||||
- created_at
|
||||
- status
|
||||
ServiceRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Service name
|
||||
domain:
|
||||
type: string
|
||||
description: Domain for the service
|
||||
targets:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ServiceTarget'
|
||||
description: List of target backends for this service
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether the service is enabled
|
||||
default: true
|
||||
pass_host_header:
|
||||
type: boolean
|
||||
description: When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
rewrite_redirects:
|
||||
type: boolean
|
||||
description: When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
auth:
|
||||
$ref: '#/components/schemas/ServiceAuthConfig'
|
||||
required:
|
||||
- name
|
||||
- domain
|
||||
- targets
|
||||
- auth
|
||||
- enabled
|
||||
ServiceTarget:
|
||||
type: object
|
||||
properties:
|
||||
target_id:
|
||||
type: string
|
||||
description: Target ID
|
||||
target_type:
|
||||
type: string
|
||||
description: Target type (e.g., "peer", "resource")
|
||||
enum: [peer, resource]
|
||||
path:
|
||||
type: string
|
||||
description: URL path prefix for this target
|
||||
protocol:
|
||||
type: string
|
||||
description: Protocol to use when connecting to the backend
|
||||
enum: [http, https]
|
||||
host:
|
||||
type: string
|
||||
description: Backend ip or domain for this target
|
||||
port:
|
||||
type: integer
|
||||
description: Backend port for this target. Use 0 or omit to use the scheme default (80 for http, 443 for https).
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether this target is enabled
|
||||
required:
|
||||
- target_id
|
||||
- target_type
|
||||
- protocol
|
||||
- port
|
||||
- enabled
|
||||
ServiceAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
password_auth:
|
||||
$ref: '#/components/schemas/PasswordAuthConfig'
|
||||
pin_auth:
|
||||
$ref: '#/components/schemas/PINAuthConfig'
|
||||
bearer_auth:
|
||||
$ref: '#/components/schemas/BearerAuthConfig'
|
||||
link_auth:
|
||||
$ref: '#/components/schemas/LinkAuthConfig'
|
||||
PasswordAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether password auth is enabled
|
||||
password:
|
||||
type: string
|
||||
description: Auth password
|
||||
required:
|
||||
- enabled
|
||||
- password
|
||||
PINAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether PIN auth is enabled
|
||||
pin:
|
||||
type: string
|
||||
description: PIN value
|
||||
required:
|
||||
- enabled
|
||||
- pin
|
||||
BearerAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether bearer auth is enabled
|
||||
distribution_groups:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: List of group IDs that can use bearer auth
|
||||
required:
|
||||
- enabled
|
||||
LinkAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether link auth is enabled
|
||||
required:
|
||||
- enabled
|
||||
ProxyCluster:
|
||||
type: object
|
||||
description: A proxy cluster represents a group of proxy nodes serving the same address
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
description: Cluster address used for CNAME targets
|
||||
example: "eu.proxy.netbird.io"
|
||||
connected_proxies:
|
||||
type: integer
|
||||
description: Number of proxy nodes connected in this cluster
|
||||
example: 3
|
||||
required:
|
||||
- address
|
||||
- connected_proxies
|
||||
ReverseProxyDomainType:
|
||||
type: string
|
||||
description: Type of Reverse Proxy Domain
|
||||
enum:
|
||||
- free
|
||||
- custom
|
||||
example: free
|
||||
ReverseProxyDomain:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Domain ID
|
||||
domain:
|
||||
type: string
|
||||
description: Domain name
|
||||
validated:
|
||||
type: boolean
|
||||
description: Whether the domain has been validated
|
||||
type:
|
||||
$ref: '#/components/schemas/ReverseProxyDomainType'
|
||||
target_cluster:
|
||||
type: string
|
||||
description: The proxy cluster this domain is validated against (only for custom domains)
|
||||
required:
|
||||
- id
|
||||
- domain
|
||||
- validated
|
||||
- type
|
||||
ReverseProxyDomainRequest:
|
||||
type: object
|
||||
properties:
|
||||
domain:
|
||||
type: string
|
||||
description: Domain name
|
||||
target_cluster:
|
||||
type: string
|
||||
description: The proxy cluster this domain should be validated against
|
||||
required:
|
||||
- domain
|
||||
- target_cluster
|
||||
InstanceStatus:
|
||||
type: object
|
||||
description: Instance status information
|
||||
@@ -6996,6 +7388,106 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/events/proxy:
|
||||
get:
|
||||
summary: List all Reverse Proxy Access Logs
|
||||
description: Returns a paginated list of all reverse proxy access log entries
|
||||
tags: [ Events ]
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: integer
|
||||
default: 1
|
||||
minimum: 1
|
||||
description: Page number for pagination (1-indexed)
|
||||
- in: query
|
||||
name: page_size
|
||||
schema:
|
||||
type: integer
|
||||
default: 50
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
description: Number of items per page (max 100)
|
||||
- in: query
|
||||
name: search
|
||||
schema:
|
||||
type: string
|
||||
description: General search across request ID, host, path, source IP, user email, and user name
|
||||
- in: query
|
||||
name: source_ip
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by source IP address
|
||||
- in: query
|
||||
name: host
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by host header
|
||||
- in: query
|
||||
name: path
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by request path (supports partial matching)
|
||||
- in: query
|
||||
name: user_id
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by authenticated user ID
|
||||
- in: query
|
||||
name: user_email
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by user email (partial matching)
|
||||
- in: query
|
||||
name: user_name
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by user name (partial matching)
|
||||
- in: query
|
||||
name: method
|
||||
schema:
|
||||
type: string
|
||||
enum: [GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS]
|
||||
description: Filter by HTTP method
|
||||
- in: query
|
||||
name: status
|
||||
schema:
|
||||
type: string
|
||||
enum: [success, failed]
|
||||
description: Filter by status (success = 2xx/3xx, failed = 1xx/4xx/5xx)
|
||||
- in: query
|
||||
name: status_code
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 100
|
||||
maximum: 599
|
||||
description: Filter by HTTP status code
|
||||
- in: query
|
||||
name: start_date
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Filter by timestamp >= start_date (RFC3339 format)
|
||||
- in: query
|
||||
name: end_date
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Filter by timestamp <= end_date (RFC3339 format)
|
||||
responses:
|
||||
"200":
|
||||
description: Paginated list of reverse proxy access logs
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProxyAccessLogsResponse"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/posture-checks:
|
||||
get:
|
||||
summary: List all Posture Checks
|
||||
@@ -9063,3 +9555,286 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/reverse-proxies/services:
|
||||
get:
|
||||
summary: List all Services
|
||||
description: Returns a list of all reverse proxy services
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of services
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Service'
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Service
|
||||
description: Creates a new reverse proxy service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
requestBody:
|
||||
description: New service request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Service created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/clusters:
|
||||
get:
|
||||
summary: List available proxy clusters
|
||||
description: Returns a list of available proxy clusters with their connection status
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of proxy clusters
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ProxyCluster'
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/services/{serviceId}:
|
||||
get:
|
||||
summary: Retrieve a Service
|
||||
description: Get information about a specific reverse proxy service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a service
|
||||
responses:
|
||||
'200':
|
||||
description: A service object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Service
|
||||
description: Update an existing service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a service
|
||||
requestBody:
|
||||
description: Service update request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ServiceRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Service updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Service
|
||||
description: Delete an existing service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a service
|
||||
responses:
|
||||
'200':
|
||||
description: Service deleted
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains:
|
||||
get:
|
||||
summary: Retrieve Service Domains
|
||||
description: Get information about domains that can be used for service endpoints.
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of ReverseProxyDomains
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ReverseProxyDomain'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Custom domain
|
||||
description: Create a new Custom domain for use with service endpoints, this will trigger an initial validation check
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
requestBody:
|
||||
description: Custom domain creation request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxyDomainRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Service created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains/{domainId}:
|
||||
delete:
|
||||
summary: Delete a Custom domain
|
||||
description: Delete an existing service custom domain
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: domainId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The custom domain ID
|
||||
responses:
|
||||
'204':
|
||||
description: Service custom domain deleted
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains/{domainId}/validate:
|
||||
get:
|
||||
summary: Validate a custom domain
|
||||
description: Trigger domain ownership validation for a custom domain
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: domainId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The custom domain ID
|
||||
responses:
|
||||
'202':
|
||||
description: Reverse proxy custom domain validation triggered
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
|
||||
@@ -114,6 +114,9 @@ const (
|
||||
EventActivityCodeRuleAdd EventActivityCode = "rule.add"
|
||||
EventActivityCodeRuleDelete EventActivityCode = "rule.delete"
|
||||
EventActivityCodeRuleUpdate EventActivityCode = "rule.update"
|
||||
EventActivityCodeServiceCreate EventActivityCode = "service.create"
|
||||
EventActivityCodeServiceDelete EventActivityCode = "service.delete"
|
||||
EventActivityCodeServiceUpdate EventActivityCode = "service.update"
|
||||
EventActivityCodeServiceUserCreate EventActivityCode = "service.user.create"
|
||||
EventActivityCodeServiceUserDelete EventActivityCode = "service.user.delete"
|
||||
EventActivityCodeSetupkeyAdd EventActivityCode = "setupkey.add"
|
||||
@@ -288,6 +291,12 @@ const (
|
||||
ResourceTypeSubnet ResourceType = "subnet"
|
||||
)
|
||||
|
||||
// Defines values for ReverseProxyDomainType.
|
||||
const (
|
||||
ReverseProxyDomainTypeCustom ReverseProxyDomainType = "custom"
|
||||
ReverseProxyDomainTypeFree ReverseProxyDomainType = "free"
|
||||
)
|
||||
|
||||
// Defines values for SentinelOneMatchAttributesNetworkStatus.
|
||||
const (
|
||||
SentinelOneMatchAttributesNetworkStatusConnected SentinelOneMatchAttributesNetworkStatus = "connected"
|
||||
@@ -295,6 +304,28 @@ const (
|
||||
SentinelOneMatchAttributesNetworkStatusQuarantined SentinelOneMatchAttributesNetworkStatus = "quarantined"
|
||||
)
|
||||
|
||||
// Defines values for ServiceMetaStatus.
|
||||
const (
|
||||
ServiceMetaStatusActive ServiceMetaStatus = "active"
|
||||
ServiceMetaStatusCertificateFailed ServiceMetaStatus = "certificate_failed"
|
||||
ServiceMetaStatusCertificatePending ServiceMetaStatus = "certificate_pending"
|
||||
ServiceMetaStatusError ServiceMetaStatus = "error"
|
||||
ServiceMetaStatusPending ServiceMetaStatus = "pending"
|
||||
ServiceMetaStatusTunnelNotCreated ServiceMetaStatus = "tunnel_not_created"
|
||||
)
|
||||
|
||||
// Defines values for ServiceTargetProtocol.
|
||||
const (
|
||||
ServiceTargetProtocolHttp ServiceTargetProtocol = "http"
|
||||
ServiceTargetProtocolHttps ServiceTargetProtocol = "https"
|
||||
)
|
||||
|
||||
// Defines values for ServiceTargetTargetType.
|
||||
const (
|
||||
ServiceTargetTargetTypePeer ServiceTargetTargetType = "peer"
|
||||
ServiceTargetTargetTypeResource ServiceTargetTargetType = "resource"
|
||||
)
|
||||
|
||||
// Defines values for TenantResponseStatus.
|
||||
const (
|
||||
TenantResponseStatusActive TenantResponseStatus = "active"
|
||||
@@ -336,6 +367,23 @@ const (
|
||||
GetApiEventsNetworkTrafficParamsDirectionINGRESS GetApiEventsNetworkTrafficParamsDirection = "INGRESS"
|
||||
)
|
||||
|
||||
// Defines values for GetApiEventsProxyParamsMethod.
|
||||
const (
|
||||
GetApiEventsProxyParamsMethodDELETE GetApiEventsProxyParamsMethod = "DELETE"
|
||||
GetApiEventsProxyParamsMethodGET GetApiEventsProxyParamsMethod = "GET"
|
||||
GetApiEventsProxyParamsMethodHEAD GetApiEventsProxyParamsMethod = "HEAD"
|
||||
GetApiEventsProxyParamsMethodOPTIONS GetApiEventsProxyParamsMethod = "OPTIONS"
|
||||
GetApiEventsProxyParamsMethodPATCH GetApiEventsProxyParamsMethod = "PATCH"
|
||||
GetApiEventsProxyParamsMethodPOST GetApiEventsProxyParamsMethod = "POST"
|
||||
GetApiEventsProxyParamsMethodPUT GetApiEventsProxyParamsMethod = "PUT"
|
||||
)
|
||||
|
||||
// Defines values for GetApiEventsProxyParamsStatus.
|
||||
const (
|
||||
GetApiEventsProxyParamsStatusFailed GetApiEventsProxyParamsStatus = "failed"
|
||||
GetApiEventsProxyParamsStatusSuccess GetApiEventsProxyParamsStatus = "success"
|
||||
)
|
||||
|
||||
// Defines values for PutApiIntegrationsMspTenantsIdInviteJSONBodyValue.
|
||||
const (
|
||||
PutApiIntegrationsMspTenantsIdInviteJSONBodyValueAccept PutApiIntegrationsMspTenantsIdInviteJSONBodyValue = "accept"
|
||||
@@ -492,6 +540,15 @@ type AvailablePorts struct {
|
||||
Udp int `json:"udp"`
|
||||
}
|
||||
|
||||
// BearerAuthConfig defines model for BearerAuthConfig.
|
||||
type BearerAuthConfig struct {
|
||||
// DistributionGroups List of group IDs that can use bearer auth
|
||||
DistributionGroups *[]string `json:"distribution_groups,omitempty"`
|
||||
|
||||
// Enabled Whether bearer auth is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// BundleParameters These parameters control what gets included in the bundle and how it is processed.
|
||||
type BundleParameters struct {
|
||||
// Anonymize Whether sensitive data should be anonymized in the bundle.
|
||||
@@ -1329,6 +1386,12 @@ type JobResponse struct {
|
||||
// JobResponseStatus defines model for JobResponse.Status.
|
||||
type JobResponseStatus string
|
||||
|
||||
// LinkAuthConfig defines model for LinkAuthConfig.
|
||||
type LinkAuthConfig struct {
|
||||
// Enabled Whether link auth is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// Location Describe geographical location information
|
||||
type Location struct {
|
||||
// CityName Commonly used English name of the city
|
||||
@@ -1699,6 +1762,24 @@ type OSVersionCheck struct {
|
||||
Windows *MinKernelVersionCheck `json:"windows,omitempty"`
|
||||
}
|
||||
|
||||
// PINAuthConfig defines model for PINAuthConfig.
|
||||
type PINAuthConfig struct {
|
||||
// Enabled Whether PIN auth is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Pin PIN value
|
||||
Pin string `json:"pin"`
|
||||
}
|
||||
|
||||
// PasswordAuthConfig defines model for PasswordAuthConfig.
|
||||
type PasswordAuthConfig struct {
|
||||
// Enabled Whether password auth is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Password Auth password
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// PasswordChangeRequest defines model for PasswordChangeRequest.
|
||||
type PasswordChangeRequest struct {
|
||||
// NewPassword The new password to set
|
||||
@@ -2301,6 +2382,78 @@ type Product struct {
|
||||
Prices []Price `json:"prices"`
|
||||
}
|
||||
|
||||
// ProxyAccessLog defines model for ProxyAccessLog.
|
||||
type ProxyAccessLog struct {
|
||||
// AuthMethodUsed Authentication method used (e.g., password, pin, oidc)
|
||||
AuthMethodUsed *string `json:"auth_method_used,omitempty"`
|
||||
|
||||
// CityName City name from geolocation
|
||||
CityName *string `json:"city_name,omitempty"`
|
||||
|
||||
// CountryCode Country code from geolocation
|
||||
CountryCode *string `json:"country_code,omitempty"`
|
||||
|
||||
// DurationMs Duration of the request in milliseconds
|
||||
DurationMs int `json:"duration_ms"`
|
||||
|
||||
// Host Host header of the request
|
||||
Host string `json:"host"`
|
||||
|
||||
// Id Unique identifier for the access log entry
|
||||
Id string `json:"id"`
|
||||
|
||||
// Method HTTP method of the request
|
||||
Method string `json:"method"`
|
||||
|
||||
// Path Path of the request
|
||||
Path string `json:"path"`
|
||||
|
||||
// Reason Reason for the request result (e.g., authentication failure)
|
||||
Reason *string `json:"reason,omitempty"`
|
||||
|
||||
// ServiceId ID of the service that handled the request
|
||||
ServiceId string `json:"service_id"`
|
||||
|
||||
// SourceIp Source IP address of the request
|
||||
SourceIp *string `json:"source_ip,omitempty"`
|
||||
|
||||
// StatusCode HTTP status code returned
|
||||
StatusCode int `json:"status_code"`
|
||||
|
||||
// Timestamp Timestamp when the request was made
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
|
||||
// UserId ID of the authenticated user, if applicable
|
||||
UserId *string `json:"user_id,omitempty"`
|
||||
}
|
||||
|
||||
// ProxyAccessLogsResponse defines model for ProxyAccessLogsResponse.
|
||||
type ProxyAccessLogsResponse struct {
|
||||
// Data List of proxy access log entries
|
||||
Data []ProxyAccessLog `json:"data"`
|
||||
|
||||
// Page Current page number
|
||||
Page int `json:"page"`
|
||||
|
||||
// PageSize Number of items per page
|
||||
PageSize int `json:"page_size"`
|
||||
|
||||
// TotalPages Total number of pages available
|
||||
TotalPages int `json:"total_pages"`
|
||||
|
||||
// TotalRecords Total number of log records available
|
||||
TotalRecords int `json:"total_records"`
|
||||
}
|
||||
|
||||
// ProxyCluster A proxy cluster represents a group of proxy nodes serving the same address
|
||||
type ProxyCluster struct {
|
||||
// Address Cluster address used for CNAME targets
|
||||
Address string `json:"address"`
|
||||
|
||||
// ConnectedProxies Number of proxy nodes connected in this cluster
|
||||
ConnectedProxies int `json:"connected_proxies"`
|
||||
}
|
||||
|
||||
// Resource defines model for Resource.
|
||||
type Resource struct {
|
||||
// Id ID of the resource
|
||||
@@ -2311,6 +2464,36 @@ type Resource struct {
|
||||
// ResourceType defines model for ResourceType.
|
||||
type ResourceType string
|
||||
|
||||
// ReverseProxyDomain defines model for ReverseProxyDomain.
|
||||
type ReverseProxyDomain struct {
|
||||
// Domain Domain name
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Id Domain ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// TargetCluster The proxy cluster this domain is validated against (only for custom domains)
|
||||
TargetCluster *string `json:"target_cluster,omitempty"`
|
||||
|
||||
// Type Type of Reverse Proxy Domain
|
||||
Type ReverseProxyDomainType `json:"type"`
|
||||
|
||||
// Validated Whether the domain has been validated
|
||||
Validated bool `json:"validated"`
|
||||
}
|
||||
|
||||
// ReverseProxyDomainRequest defines model for ReverseProxyDomainRequest.
|
||||
type ReverseProxyDomainRequest struct {
|
||||
// Domain Domain name
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// TargetCluster The proxy cluster this domain should be validated against
|
||||
TargetCluster string `json:"target_cluster"`
|
||||
}
|
||||
|
||||
// ReverseProxyDomainType Type of Reverse Proxy Domain
|
||||
type ReverseProxyDomainType string
|
||||
|
||||
// Route defines model for Route.
|
||||
type Route struct {
|
||||
// AccessControlGroups Access control group identifier associated with route.
|
||||
@@ -2470,6 +2653,112 @@ type SentinelOneMatchAttributes struct {
|
||||
// SentinelOneMatchAttributesNetworkStatus The current network connectivity status of the device
|
||||
type SentinelOneMatchAttributesNetworkStatus string
|
||||
|
||||
// Service defines model for Service.
|
||||
type Service struct {
|
||||
Auth ServiceAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the service
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the service is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Service ID
|
||||
Id string `json:"id"`
|
||||
Meta ServiceMeta `json:"meta"`
|
||||
|
||||
// Name Service name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// ProxyCluster The proxy cluster handling this service (derived from domain)
|
||||
ProxyCluster *string `json:"proxy_cluster,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this service
|
||||
Targets []ServiceTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ServiceAuthConfig defines model for ServiceAuthConfig.
|
||||
type ServiceAuthConfig struct {
|
||||
BearerAuth *BearerAuthConfig `json:"bearer_auth,omitempty"`
|
||||
LinkAuth *LinkAuthConfig `json:"link_auth,omitempty"`
|
||||
PasswordAuth *PasswordAuthConfig `json:"password_auth,omitempty"`
|
||||
PinAuth *PINAuthConfig `json:"pin_auth,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceMeta defines model for ServiceMeta.
|
||||
type ServiceMeta struct {
|
||||
// CertificateIssuedAt Timestamp when the certificate was issued (empty if not yet issued)
|
||||
CertificateIssuedAt *time.Time `json:"certificate_issued_at,omitempty"`
|
||||
|
||||
// CreatedAt Timestamp when the service was created
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// Status Current status of the service
|
||||
Status ServiceMetaStatus `json:"status"`
|
||||
}
|
||||
|
||||
// ServiceMetaStatus Current status of the service
|
||||
type ServiceMetaStatus string
|
||||
|
||||
// ServiceRequest defines model for ServiceRequest.
|
||||
type ServiceRequest struct {
|
||||
Auth ServiceAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the service
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the service is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Name Service name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this service
|
||||
Targets []ServiceTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ServiceTarget defines model for ServiceTarget.
|
||||
type ServiceTarget struct {
|
||||
// Enabled Whether this target is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Host Backend ip or domain for this target
|
||||
Host *string `json:"host,omitempty"`
|
||||
|
||||
// Path URL path prefix for this target
|
||||
Path *string `json:"path,omitempty"`
|
||||
|
||||
// Port Backend port for this target. Use 0 or omit to use the scheme default (80 for http, 443 for https).
|
||||
Port int `json:"port"`
|
||||
|
||||
// Protocol Protocol to use when connecting to the backend
|
||||
Protocol ServiceTargetProtocol `json:"protocol"`
|
||||
|
||||
// TargetId Target ID
|
||||
TargetId string `json:"target_id"`
|
||||
|
||||
// TargetType Target type (e.g., "peer", "resource")
|
||||
TargetType ServiceTargetTargetType `json:"target_type"`
|
||||
}
|
||||
|
||||
// ServiceTargetProtocol Protocol to use when connecting to the backend
|
||||
type ServiceTargetProtocol string
|
||||
|
||||
// ServiceTargetTargetType Target type (e.g., "peer", "resource")
|
||||
type ServiceTargetTargetType string
|
||||
|
||||
// SetupKey defines model for SetupKey.
|
||||
type SetupKey struct {
|
||||
// AllowExtraDnsLabels Allow extra DNS labels to be added to the peer
|
||||
@@ -3032,6 +3321,57 @@ type GetApiEventsNetworkTrafficParamsConnectionType string
|
||||
// GetApiEventsNetworkTrafficParamsDirection defines parameters for GetApiEventsNetworkTraffic.
|
||||
type GetApiEventsNetworkTrafficParamsDirection string
|
||||
|
||||
// GetApiEventsProxyParams defines parameters for GetApiEventsProxy.
|
||||
type GetApiEventsProxyParams struct {
|
||||
// Page Page number for pagination (1-indexed)
|
||||
Page *int `form:"page,omitempty" json:"page,omitempty"`
|
||||
|
||||
// PageSize Number of items per page (max 100)
|
||||
PageSize *int `form:"page_size,omitempty" json:"page_size,omitempty"`
|
||||
|
||||
// Search General search across request ID, host, path, source IP, user email, and user name
|
||||
Search *string `form:"search,omitempty" json:"search,omitempty"`
|
||||
|
||||
// SourceIp Filter by source IP address
|
||||
SourceIp *string `form:"source_ip,omitempty" json:"source_ip,omitempty"`
|
||||
|
||||
// Host Filter by host header
|
||||
Host *string `form:"host,omitempty" json:"host,omitempty"`
|
||||
|
||||
// Path Filter by request path (supports partial matching)
|
||||
Path *string `form:"path,omitempty" json:"path,omitempty"`
|
||||
|
||||
// UserId Filter by authenticated user ID
|
||||
UserId *string `form:"user_id,omitempty" json:"user_id,omitempty"`
|
||||
|
||||
// UserEmail Filter by user email (partial matching)
|
||||
UserEmail *string `form:"user_email,omitempty" json:"user_email,omitempty"`
|
||||
|
||||
// UserName Filter by user name (partial matching)
|
||||
UserName *string `form:"user_name,omitempty" json:"user_name,omitempty"`
|
||||
|
||||
// Method Filter by HTTP method
|
||||
Method *GetApiEventsProxyParamsMethod `form:"method,omitempty" json:"method,omitempty"`
|
||||
|
||||
// Status Filter by status (success = 2xx/3xx, failed = 1xx/4xx/5xx)
|
||||
Status *GetApiEventsProxyParamsStatus `form:"status,omitempty" json:"status,omitempty"`
|
||||
|
||||
// StatusCode Filter by HTTP status code
|
||||
StatusCode *int `form:"status_code,omitempty" json:"status_code,omitempty"`
|
||||
|
||||
// StartDate Filter by timestamp >= start_date (RFC3339 format)
|
||||
StartDate *time.Time `form:"start_date,omitempty" json:"start_date,omitempty"`
|
||||
|
||||
// EndDate Filter by timestamp <= end_date (RFC3339 format)
|
||||
EndDate *time.Time `form:"end_date,omitempty" json:"end_date,omitempty"`
|
||||
}
|
||||
|
||||
// GetApiEventsProxyParamsMethod defines parameters for GetApiEventsProxy.
|
||||
type GetApiEventsProxyParamsMethod string
|
||||
|
||||
// GetApiEventsProxyParamsStatus defines parameters for GetApiEventsProxy.
|
||||
type GetApiEventsProxyParamsStatus string
|
||||
|
||||
// GetApiGroupsParams defines parameters for GetApiGroups.
|
||||
type GetApiGroupsParams struct {
|
||||
// Name Filter groups by name (exact match)
|
||||
@@ -3269,6 +3609,15 @@ type PostApiPostureChecksJSONRequestBody = PostureCheckUpdate
|
||||
// PutApiPostureChecksPostureCheckIdJSONRequestBody defines body for PutApiPostureChecksPostureCheckId for application/json ContentType.
|
||||
type PutApiPostureChecksPostureCheckIdJSONRequestBody = PostureCheckUpdate
|
||||
|
||||
// PostApiReverseProxiesDomainsJSONRequestBody defines body for PostApiReverseProxiesDomains for application/json ContentType.
|
||||
type PostApiReverseProxiesDomainsJSONRequestBody = ReverseProxyDomainRequest
|
||||
|
||||
// PostApiReverseProxiesServicesJSONRequestBody defines body for PostApiReverseProxiesServices for application/json ContentType.
|
||||
type PostApiReverseProxiesServicesJSONRequestBody = ServiceRequest
|
||||
|
||||
// PutApiReverseProxiesServicesServiceIdJSONRequestBody defines body for PutApiReverseProxiesServicesServiceId for application/json ContentType.
|
||||
type PutApiReverseProxiesServicesServiceIdJSONRequestBody = ServiceRequest
|
||||
|
||||
// PostApiRoutesJSONRequestBody defines body for PostApiRoutes for application/json ContentType.
|
||||
type PostApiRoutesJSONRequestBody = RouteRequest
|
||||
|
||||
|
||||
@@ -14,4 +14,5 @@ cd "$script_path"
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
||||
protoc -I ./ ./management.proto --go_out=../ --go-grpc_out=../
|
||||
protoc -I ./ ./proxy_service.proto --go_out=../ --go-grpc_out=../
|
||||
cd "$old_pwd"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v6.33.1
|
||||
// protoc v6.33.0
|
||||
// source: management.proto
|
||||
|
||||
package proto
|
||||
|
||||
2061
shared/management/proto/proxy_service.pb.go
Normal file
2061
shared/management/proto/proxy_service.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
185
shared/management/proto/proxy_service.proto
Normal file
185
shared/management/proto/proxy_service.proto
Normal file
@@ -0,0 +1,185 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package management;
|
||||
|
||||
option go_package = "/proto";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// ProxyService - Management is the SERVER, Proxy is the CLIENT
|
||||
// Proxy initiates connection to management
|
||||
service ProxyService {
|
||||
rpc GetMappingUpdate(GetMappingUpdateRequest) returns (stream GetMappingUpdateResponse);
|
||||
|
||||
rpc SendAccessLog(SendAccessLogRequest) returns (SendAccessLogResponse);
|
||||
|
||||
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse);
|
||||
|
||||
rpc SendStatusUpdate(SendStatusUpdateRequest) returns (SendStatusUpdateResponse);
|
||||
|
||||
rpc CreateProxyPeer(CreateProxyPeerRequest) returns (CreateProxyPeerResponse);
|
||||
|
||||
rpc GetOIDCURL(GetOIDCURLRequest) returns (GetOIDCURLResponse);
|
||||
|
||||
// ValidateSession validates a session token and checks user access permissions.
|
||||
// Called by the proxy after receiving a session token from OIDC callback.
|
||||
rpc ValidateSession(ValidateSessionRequest) returns (ValidateSessionResponse);
|
||||
}
|
||||
|
||||
// GetMappingUpdateRequest is sent to initialise a mapping stream.
|
||||
message GetMappingUpdateRequest {
|
||||
string proxy_id = 1;
|
||||
string version = 2;
|
||||
google.protobuf.Timestamp started_at = 3;
|
||||
string address = 4;
|
||||
}
|
||||
|
||||
// GetMappingUpdateResponse contains zero or more ProxyMappings.
|
||||
// No mappings may be sent to test the liveness of the Proxy.
|
||||
// Mappings that are sent should be interpreted by the Proxy appropriately.
|
||||
message GetMappingUpdateResponse {
|
||||
repeated ProxyMapping mapping = 1;
|
||||
// initial_sync_complete is set on the last message of the initial snapshot.
|
||||
// The proxy uses this to signal that startup is complete.
|
||||
bool initial_sync_complete = 2;
|
||||
}
|
||||
|
||||
enum ProxyMappingUpdateType {
|
||||
UPDATE_TYPE_CREATED = 0;
|
||||
UPDATE_TYPE_MODIFIED = 1;
|
||||
UPDATE_TYPE_REMOVED = 2;
|
||||
}
|
||||
|
||||
message PathMapping {
|
||||
string path = 1;
|
||||
string target = 2;
|
||||
}
|
||||
|
||||
message Authentication {
|
||||
string session_key = 1;
|
||||
int64 max_session_age_seconds = 2;
|
||||
bool password = 3;
|
||||
bool pin = 4;
|
||||
bool oidc = 5;
|
||||
}
|
||||
|
||||
message ProxyMapping {
|
||||
ProxyMappingUpdateType type = 1;
|
||||
string id = 2;
|
||||
string account_id = 3;
|
||||
string domain = 4;
|
||||
repeated PathMapping path = 5;
|
||||
string auth_token = 6;
|
||||
Authentication auth = 7;
|
||||
// When true, the original Host header from the client request is passed
|
||||
// through to the backend instead of being rewritten to the backend's address.
|
||||
bool pass_host_header = 8;
|
||||
// When true, Location headers in backend responses are rewritten to replace
|
||||
// the backend address with the public-facing domain.
|
||||
bool rewrite_redirects = 9;
|
||||
}
|
||||
|
||||
// SendAccessLogRequest consists of one or more AccessLogs from a Proxy.
|
||||
message SendAccessLogRequest {
|
||||
AccessLog log = 1;
|
||||
}
|
||||
|
||||
// SendAccessLogResponse is intentionally empty to allow for future expansion.
|
||||
message SendAccessLogResponse {}
|
||||
|
||||
message AccessLog {
|
||||
google.protobuf.Timestamp timestamp = 1;
|
||||
string log_id = 2;
|
||||
string account_id = 3;
|
||||
string service_id = 4;
|
||||
string host = 5;
|
||||
string path = 6;
|
||||
int64 duration_ms = 7;
|
||||
string method = 8;
|
||||
int32 response_code = 9;
|
||||
string source_ip = 10;
|
||||
string auth_mechanism = 11;
|
||||
string user_id = 12;
|
||||
bool auth_success = 13;
|
||||
}
|
||||
|
||||
message AuthenticateRequest {
|
||||
string id = 1;
|
||||
string account_id = 2;
|
||||
oneof request {
|
||||
PasswordRequest password = 3;
|
||||
PinRequest pin = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message PasswordRequest {
|
||||
string password = 1;
|
||||
}
|
||||
|
||||
message PinRequest {
|
||||
string pin = 1;
|
||||
}
|
||||
|
||||
message AuthenticateResponse {
|
||||
bool success = 1;
|
||||
string session_token = 2;
|
||||
}
|
||||
|
||||
enum ProxyStatus {
|
||||
PROXY_STATUS_PENDING = 0;
|
||||
PROXY_STATUS_ACTIVE = 1;
|
||||
PROXY_STATUS_TUNNEL_NOT_CREATED = 2;
|
||||
PROXY_STATUS_CERTIFICATE_PENDING = 3;
|
||||
PROXY_STATUS_CERTIFICATE_FAILED = 4;
|
||||
PROXY_STATUS_ERROR = 5;
|
||||
}
|
||||
|
||||
// SendStatusUpdateRequest is sent by the proxy to update its status
|
||||
message SendStatusUpdateRequest {
|
||||
string service_id = 1;
|
||||
string account_id = 2;
|
||||
ProxyStatus status = 3;
|
||||
bool certificate_issued = 4;
|
||||
optional string error_message = 5;
|
||||
}
|
||||
|
||||
// SendStatusUpdateResponse is intentionally empty to allow for future expansion
|
||||
message SendStatusUpdateResponse {}
|
||||
|
||||
// CreateProxyPeerRequest is sent by the proxy to create a peer connection
|
||||
// The token is a one-time authentication token sent via ProxyMapping
|
||||
message CreateProxyPeerRequest {
|
||||
string service_id = 1;
|
||||
string account_id = 2;
|
||||
string token = 3;
|
||||
string wireguard_public_key = 4;
|
||||
string cluster = 5;
|
||||
}
|
||||
|
||||
// CreateProxyPeerResponse contains the result of peer creation
|
||||
message CreateProxyPeerResponse {
|
||||
bool success = 1;
|
||||
optional string error_message = 2;
|
||||
}
|
||||
|
||||
message GetOIDCURLRequest {
|
||||
string id = 1;
|
||||
string account_id = 2;
|
||||
string redirect_url = 3;
|
||||
}
|
||||
|
||||
message GetOIDCURLResponse {
|
||||
string url = 1;
|
||||
}
|
||||
|
||||
message ValidateSessionRequest {
|
||||
string domain = 1;
|
||||
string session_token = 2;
|
||||
}
|
||||
|
||||
message ValidateSessionResponse {
|
||||
bool valid = 1;
|
||||
string user_id = 2;
|
||||
string user_email = 3;
|
||||
string denied_reason = 4;
|
||||
}
|
||||
349
shared/management/proto/proxy_service_grpc.pb.go
Normal file
349
shared/management/proto/proxy_service_grpc.pb.go
Normal file
@@ -0,0 +1,349 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// ProxyServiceClient is the client API for ProxyService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ProxyServiceClient interface {
|
||||
GetMappingUpdate(ctx context.Context, in *GetMappingUpdateRequest, opts ...grpc.CallOption) (ProxyService_GetMappingUpdateClient, error)
|
||||
SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error)
|
||||
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
|
||||
SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error)
|
||||
CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error)
|
||||
GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error)
|
||||
// ValidateSession validates a session token and checks user access permissions.
|
||||
// Called by the proxy after receiving a session token from OIDC callback.
|
||||
ValidateSession(ctx context.Context, in *ValidateSessionRequest, opts ...grpc.CallOption) (*ValidateSessionResponse, error)
|
||||
}
|
||||
|
||||
type proxyServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewProxyServiceClient(cc grpc.ClientConnInterface) ProxyServiceClient {
|
||||
return &proxyServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) GetMappingUpdate(ctx context.Context, in *GetMappingUpdateRequest, opts ...grpc.CallOption) (ProxyService_GetMappingUpdateClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &ProxyService_ServiceDesc.Streams[0], "/management.ProxyService/GetMappingUpdate", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &proxyServiceGetMappingUpdateClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type ProxyService_GetMappingUpdateClient interface {
|
||||
Recv() (*GetMappingUpdateResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type proxyServiceGetMappingUpdateClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *proxyServiceGetMappingUpdateClient) Recv() (*GetMappingUpdateResponse, error) {
|
||||
m := new(GetMappingUpdateResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error) {
|
||||
out := new(SendAccessLogResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/SendAccessLog", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error) {
|
||||
out := new(AuthenticateResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/Authenticate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error) {
|
||||
out := new(SendStatusUpdateResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/SendStatusUpdate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error) {
|
||||
out := new(CreateProxyPeerResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/CreateProxyPeer", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error) {
|
||||
out := new(GetOIDCURLResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/GetOIDCURL", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) ValidateSession(ctx context.Context, in *ValidateSessionRequest, opts ...grpc.CallOption) (*ValidateSessionResponse, error) {
|
||||
out := new(ValidateSessionResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/ValidateSession", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ProxyServiceServer is the server API for ProxyService service.
|
||||
// All implementations must embed UnimplementedProxyServiceServer
|
||||
// for forward compatibility
|
||||
type ProxyServiceServer interface {
|
||||
GetMappingUpdate(*GetMappingUpdateRequest, ProxyService_GetMappingUpdateServer) error
|
||||
SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error)
|
||||
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
|
||||
SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error)
|
||||
CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error)
|
||||
GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error)
|
||||
// ValidateSession validates a session token and checks user access permissions.
|
||||
// Called by the proxy after receiving a session token from OIDC callback.
|
||||
ValidateSession(context.Context, *ValidateSessionRequest) (*ValidateSessionResponse, error)
|
||||
mustEmbedUnimplementedProxyServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedProxyServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedProxyServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedProxyServiceServer) GetMappingUpdate(*GetMappingUpdateRequest, ProxyService_GetMappingUpdateServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetMappingUpdate not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendAccessLog not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendStatusUpdate not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateProxyPeer not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetOIDCURL not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) ValidateSession(context.Context, *ValidateSessionRequest) (*ValidateSessionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ValidateSession not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) mustEmbedUnimplementedProxyServiceServer() {}
|
||||
|
||||
// UnsafeProxyServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ProxyServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeProxyServiceServer interface {
|
||||
mustEmbedUnimplementedProxyServiceServer()
|
||||
}
|
||||
|
||||
func RegisterProxyServiceServer(s grpc.ServiceRegistrar, srv ProxyServiceServer) {
|
||||
s.RegisterService(&ProxyService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ProxyService_GetMappingUpdate_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetMappingUpdateRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ProxyServiceServer).GetMappingUpdate(m, &proxyServiceGetMappingUpdateServer{stream})
|
||||
}
|
||||
|
||||
type ProxyService_GetMappingUpdateServer interface {
|
||||
Send(*GetMappingUpdateResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type proxyServiceGetMappingUpdateServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *proxyServiceGetMappingUpdateServer) Send(m *GetMappingUpdateResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _ProxyService_SendAccessLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SendAccessLogRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).SendAccessLog(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/SendAccessLog",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).SendAccessLog(ctx, req.(*SendAccessLogRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AuthenticateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).Authenticate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/Authenticate",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).Authenticate(ctx, req.(*AuthenticateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_SendStatusUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SendStatusUpdateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/SendStatusUpdate",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, req.(*SendStatusUpdateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_CreateProxyPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CreateProxyPeerRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/CreateProxyPeer",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, req.(*CreateProxyPeerRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_GetOIDCURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetOIDCURLRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).GetOIDCURL(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/GetOIDCURL",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).GetOIDCURL(ctx, req.(*GetOIDCURLRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_ValidateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ValidateSessionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).ValidateSession(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/ValidateSession",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).ValidateSession(ctx, req.(*ValidateSessionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ProxyService_ServiceDesc is the grpc.ServiceDesc for ProxyService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ProxyService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "management.ProxyService",
|
||||
HandlerType: (*ProxyServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "SendAccessLog",
|
||||
Handler: _ProxyService_SendAccessLog_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Authenticate",
|
||||
Handler: _ProxyService_Authenticate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SendStatusUpdate",
|
||||
Handler: _ProxyService_SendStatusUpdate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CreateProxyPeer",
|
||||
Handler: _ProxyService_CreateProxyPeer_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetOIDCURL",
|
||||
Handler: _ProxyService_GetOIDCURL_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ValidateSession",
|
||||
Handler: _ProxyService_ValidateSession_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetMappingUpdate",
|
||||
Handler: _ProxyService_GetMappingUpdate_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "proxy_service.proto",
|
||||
}
|
||||
@@ -262,3 +262,11 @@ func NewZoneNotFoundError(zoneID string) error {
|
||||
func NewDNSRecordNotFoundError(recordID string) error {
|
||||
return Errorf(NotFound, "dns record: %s not found", recordID)
|
||||
}
|
||||
|
||||
func NewResourceInUseError(resourceID string, proxyID string) error {
|
||||
return Errorf(PreconditionFailed, "resource %s is in use by proxy %s", resourceID, proxyID)
|
||||
}
|
||||
|
||||
func NewPeerInUseError(peerID string, proxyID string) error {
|
||||
return Errorf(PreconditionFailed, "peer %s is in use by proxy %s", peerID, proxyID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user