mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-19 13:19:06 +02:00
Merge branch 'main' into refactor/permissions-manager
# Conflicts: # management/internals/modules/reverseproxy/service/manager/api.go # management/server/http/testing/testing_tools/channel/channel.go
This commit is contained in:
@@ -22,6 +22,7 @@ type Client interface {
|
||||
GetDeviceAuthorizationFlow(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
||||
GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
||||
GetNetworkMap(sysInfo *system.Info) (*proto.NetworkMap, error)
|
||||
GetServerURL() string
|
||||
IsHealthy() bool
|
||||
SyncMeta(sysInfo *system.Info) error
|
||||
Logout() error
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -29,6 +31,10 @@ import (
|
||||
const ConnectTimeout = 10 * time.Second
|
||||
|
||||
const (
|
||||
// EnvMaxRecvMsgSize overrides the default gRPC max receive message size (4 MB)
|
||||
// for the management client connection. Value is in bytes.
|
||||
EnvMaxRecvMsgSize = "NB_MANAGEMENT_GRPC_MAX_MSG_SIZE"
|
||||
|
||||
errMsgMgmtPublicKey = "failed getting Management Service public key: %s"
|
||||
errMsgNoMgmtConnection = "no connection to management"
|
||||
)
|
||||
@@ -46,6 +52,7 @@ type GrpcClient struct {
|
||||
conn *grpc.ClientConn
|
||||
connStateCallback ConnStateNotifier
|
||||
connStateCallbackLock sync.RWMutex
|
||||
serverURL string
|
||||
}
|
||||
|
||||
type ExposeRequest struct {
|
||||
@@ -66,13 +73,41 @@ type ExposeResponse struct {
|
||||
PortAutoAssigned bool
|
||||
}
|
||||
|
||||
// MaxRecvMsgSize returns the configured max gRPC receive message size from
|
||||
// the environment, or 0 if unset (which uses the gRPC default of 4 MB).
|
||||
func MaxRecvMsgSize() int {
|
||||
val := os.Getenv(EnvMaxRecvMsgSize)
|
||||
if val == "" {
|
||||
return 0
|
||||
}
|
||||
|
||||
size, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
log.Warnf("invalid %s value %q, using default: %v", EnvMaxRecvMsgSize, val, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
log.Warnf("invalid %s value %d, must be positive, using default", EnvMaxRecvMsgSize, size)
|
||||
return 0
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
// NewClient creates a new client to Management service
|
||||
func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*GrpcClient, error) {
|
||||
var conn *grpc.ClientConn
|
||||
|
||||
var extraOpts []grpc.DialOption
|
||||
if maxSize := MaxRecvMsgSize(); maxSize > 0 {
|
||||
extraOpts = append(extraOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxSize)))
|
||||
log.Infof("management gRPC max receive message size set to %d bytes", maxSize)
|
||||
}
|
||||
|
||||
operation := func() error {
|
||||
var err error
|
||||
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent)
|
||||
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent, extraOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create connection: %w", err)
|
||||
}
|
||||
@@ -93,9 +128,15 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
|
||||
ctx: ctx,
|
||||
conn: conn,
|
||||
connStateCallbackLock: sync.RWMutex{},
|
||||
serverURL: addr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetServerURL returns the management server URL
|
||||
func (c *GrpcClient) GetServerURL() string {
|
||||
return c.serverURL
|
||||
}
|
||||
|
||||
// Close closes connection to the Management Service
|
||||
func (c *GrpcClient) Close() error {
|
||||
return c.conn.Close()
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
mgmtProto "github.com/netbirdio/netbird/shared/management/proto"
|
||||
)
|
||||
|
||||
func TestMaxRecvMsgSize(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
envValue string
|
||||
expected int
|
||||
}{
|
||||
{name: "unset returns 0", envValue: "", expected: 0},
|
||||
{name: "valid value", envValue: "10485760", expected: 10485760},
|
||||
{name: "non-numeric returns 0", envValue: "abc", expected: 0},
|
||||
{name: "negative returns 0", envValue: "-1", expected: 0},
|
||||
{name: "zero returns 0", envValue: "0", expected: 0},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv(EnvMaxRecvMsgSize, tt.envValue)
|
||||
if tt.envValue == "" {
|
||||
os.Unsetenv(EnvMaxRecvMsgSize)
|
||||
}
|
||||
assert.Equal(t, tt.expected, MaxRecvMsgSize())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// largeSyncServer implements just the Sync RPC, returning a response larger than the default 4MB limit.
|
||||
type largeSyncServer struct {
|
||||
mgmtProto.UnimplementedManagementServiceServer
|
||||
responseSize int
|
||||
}
|
||||
|
||||
func (s *largeSyncServer) GetServerKey(_ context.Context, _ *mgmtProto.Empty) (*mgmtProto.ServerKeyResponse, error) {
|
||||
// Return a response with a large WiretrusteeConfig to exceed the default limit.
|
||||
padding := strings.Repeat("x", s.responseSize)
|
||||
return &mgmtProto.ServerKeyResponse{
|
||||
Key: padding,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestMaxRecvMsgSizeIntegration(t *testing.T) {
|
||||
const payloadSize = 5 * 1024 * 1024 // 5MB, exceeds 4MB default
|
||||
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
|
||||
srv := grpc.NewServer()
|
||||
mgmtProto.RegisterManagementServiceServer(srv, &largeSyncServer{responseSize: payloadSize})
|
||||
go func() { _ = srv.Serve(lis) }()
|
||||
t.Cleanup(srv.Stop)
|
||||
|
||||
t.Run("default limit rejects large message", func(t *testing.T) {
|
||||
conn, err := grpc.NewClient(
|
||||
lis.Addr().String(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
client := mgmtProto.NewManagementServiceClient(conn)
|
||||
_, err = client.GetServerKey(context.Background(), &mgmtProto.Empty{})
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "received message larger than max")
|
||||
})
|
||||
|
||||
t.Run("increased limit accepts large message", func(t *testing.T) {
|
||||
conn, err := grpc.NewClient(
|
||||
lis.Addr().String(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(10*1024*1024)),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
client := mgmtProto.NewManagementServiceClient(conn)
|
||||
resp, err := client.GetServerKey(context.Background(), &mgmtProto.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resp.Key, payloadSize)
|
||||
})
|
||||
}
|
||||
@@ -19,6 +19,7 @@ type MockClient struct {
|
||||
LoginFunc func(serverKey wgtypes.Key, info *system.Info, sshKey []byte, dnsLabels domain.List) (*proto.LoginResponse, error)
|
||||
GetDeviceAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
|
||||
GetPKCEAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
|
||||
GetServerURLFunc func() string
|
||||
SyncMetaFunc func(sysInfo *system.Info) error
|
||||
LogoutFunc func() error
|
||||
JobFunc func(ctx context.Context, msgHandler func(msg *proto.JobRequest) *proto.JobResponse) error
|
||||
@@ -92,6 +93,14 @@ func (m *MockClient) GetNetworkMap(_ *system.Info) (*proto.NetworkMap, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetServerURL mock implementation of GetServerURL from mgm.Client interface
|
||||
func (m *MockClient) GetServerURL() string {
|
||||
if m.GetServerURLFunc == nil {
|
||||
return ""
|
||||
}
|
||||
return m.GetServerURLFunc()
|
||||
}
|
||||
|
||||
func (m *MockClient) SyncMeta(sysInfo *system.Info) error {
|
||||
if m.SyncMetaFunc == nil {
|
||||
return nil
|
||||
|
||||
@@ -89,6 +89,10 @@ tags:
|
||||
- name: Event Streaming Integrations
|
||||
description: Manage event streaming integrations.
|
||||
x-cloud-only: true
|
||||
- name: Notifications
|
||||
description: Manage notification channels for account event alerts.
|
||||
x-cloud-only: true
|
||||
|
||||
|
||||
components:
|
||||
schemas:
|
||||
@@ -2995,6 +2999,11 @@ components:
|
||||
type: boolean
|
||||
description: Whether the service is enabled
|
||||
example: true
|
||||
terminated:
|
||||
type: boolean
|
||||
description: Whether the service has been terminated. Terminated services cannot be updated. Services that violate the Terms of Service will be terminated.
|
||||
readOnly: true
|
||||
example: false
|
||||
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
|
||||
@@ -3336,6 +3345,10 @@ components:
|
||||
type: boolean
|
||||
description: Whether the cluster supports binding arbitrary TCP/UDP ports
|
||||
example: true
|
||||
require_subdomain:
|
||||
type: boolean
|
||||
description: Whether a subdomain label is required in front of this domain. When true, the domain cannot be used bare.
|
||||
example: false
|
||||
required:
|
||||
- id
|
||||
- domain
|
||||
@@ -4381,6 +4394,123 @@ components:
|
||||
type: string
|
||||
description: The newly generated SCIM API token
|
||||
example: "nbs_F3f0d..."
|
||||
NotificationChannelType:
|
||||
type: string
|
||||
description: The type of notification channel.
|
||||
enum:
|
||||
- email
|
||||
- webhook
|
||||
example: "email"
|
||||
NotificationEventType:
|
||||
type: string
|
||||
description: |
|
||||
An activity event type code. See `GET /api/integrations/notifications/types` for the full list
|
||||
of supported event types and their human-readable descriptions.
|
||||
example: "user.join"
|
||||
EmailTarget:
|
||||
type: object
|
||||
description: Target configuration for email notification channels.
|
||||
properties:
|
||||
emails:
|
||||
type: array
|
||||
description: List of email addresses to send notifications to.
|
||||
minItems: 1
|
||||
items:
|
||||
type: string
|
||||
format: email
|
||||
example: [ "admin@example.com", "ops@example.com" ]
|
||||
required:
|
||||
- emails
|
||||
WebhookTarget:
|
||||
type: object
|
||||
description: Target configuration for webhook notification channels.
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
format: uri
|
||||
description: The webhook endpoint URL to send notifications to.
|
||||
example: "https://hooks.example.com/netbird"
|
||||
headers:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |
|
||||
Custom HTTP headers sent with each webhook request.
|
||||
Values are write-only; in GET responses all values are masked.
|
||||
example:
|
||||
Authorization: "Bearer token"
|
||||
X-Webhook-Secret: "secret"
|
||||
required:
|
||||
- url
|
||||
NotificationChannelRequest:
|
||||
type: object
|
||||
description: Request body for creating or updating a notification channel.
|
||||
properties:
|
||||
type:
|
||||
$ref: '#/components/schemas/NotificationChannelType'
|
||||
target:
|
||||
description: |
|
||||
Channel-specific target configuration. The shape depends on the `type` field:
|
||||
- `email`: requires an `EmailTarget` object
|
||||
- `webhook`: requires a `WebhookTarget` object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/EmailTarget'
|
||||
- $ref: '#/components/schemas/WebhookTarget'
|
||||
event_types:
|
||||
type: array
|
||||
description: List of activity event type codes this channel subscribes to.
|
||||
items:
|
||||
$ref: '#/components/schemas/NotificationEventType'
|
||||
example: [ "user.join", "peer.user.add", "peer.login.expire" ]
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether this notification channel is active.
|
||||
example: true
|
||||
required:
|
||||
- type
|
||||
- event_types
|
||||
- enabled
|
||||
NotificationChannelResponse:
|
||||
type: object
|
||||
description: A notification channel configuration.
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Unique identifier of the notification channel.
|
||||
readOnly: true
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
type:
|
||||
$ref: '#/components/schemas/NotificationChannelType'
|
||||
target:
|
||||
description: |
|
||||
Channel-specific target configuration. The shape depends on the `type` field:
|
||||
- `email`: an `EmailTarget` object
|
||||
- `webhook`: a `WebhookTarget` object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/EmailTarget'
|
||||
- $ref: '#/components/schemas/WebhookTarget'
|
||||
event_types:
|
||||
type: array
|
||||
description: List of activity event type codes this channel subscribes to.
|
||||
items:
|
||||
$ref: '#/components/schemas/NotificationEventType'
|
||||
example: [ "user.join", "peer.user.add", "peer.login.expire" ]
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether this notification channel is active.
|
||||
example: true
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
- event_types
|
||||
- enabled
|
||||
NotificationTypeEntry:
|
||||
type: object
|
||||
description: A map of event type codes to their human-readable descriptions.
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
user.join: "User joined"
|
||||
BypassResponse:
|
||||
type: object
|
||||
description: Response for bypassed peer operations.
|
||||
@@ -10058,3 +10188,172 @@ paths:
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/integrations/notifications/types:
|
||||
get:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: List Notification Event Types
|
||||
description: |
|
||||
Returns a map of all supported activity event type codes to their
|
||||
human-readable descriptions. Use these codes when configuring
|
||||
`event_types` on notification channels.
|
||||
operationId: listNotificationEventTypes
|
||||
responses:
|
||||
'200':
|
||||
description: A map of event type codes to descriptions.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationTypeEntry'
|
||||
'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/integrations/notifications/channels:
|
||||
get:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: List Notification Channels
|
||||
description: Retrieves all notification channels configured for the authenticated account.
|
||||
operationId: listNotificationChannels
|
||||
responses:
|
||||
'200':
|
||||
description: A list of notification channels.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/NotificationChannelResponse'
|
||||
'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:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: Create Notification Channel
|
||||
description: |
|
||||
Creates a new notification channel for the authenticated account.
|
||||
Supported channel types are `email` and `webhook`.
|
||||
operationId: createNotificationChannel
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationChannelRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Notification channel created successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationChannelResponse'
|
||||
'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/integrations/notifications/channels/{channelId}:
|
||||
parameters:
|
||||
- name: channelId
|
||||
in: path
|
||||
required: true
|
||||
description: The unique identifier of the notification channel.
|
||||
schema:
|
||||
type: string
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
get:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: Get Notification Channel
|
||||
description: Retrieves a specific notification channel by its ID.
|
||||
operationId: getNotificationChannel
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully retrieved the notification channel.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationChannelResponse'
|
||||
'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:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: Update Notification Channel
|
||||
description: Updates an existing notification channel.
|
||||
operationId: updateNotificationChannel
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationChannelRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Notification channel updated successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NotificationChannelResponse'
|
||||
'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:
|
||||
tags:
|
||||
- Notifications
|
||||
summary: Delete Notification Channel
|
||||
description: Deletes a notification channel by its ID.
|
||||
operationId: deleteNotificationChannel
|
||||
responses:
|
||||
'200':
|
||||
description: Notification channel deleted successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
example: { }
|
||||
'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"
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/oapi-codegen/runtime"
|
||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -664,6 +665,24 @@ func (e NetworkResourceType) Valid() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Defines values for NotificationChannelType.
|
||||
const (
|
||||
NotificationChannelTypeEmail NotificationChannelType = "email"
|
||||
NotificationChannelTypeWebhook NotificationChannelType = "webhook"
|
||||
)
|
||||
|
||||
// Valid indicates whether the value is a known member of the NotificationChannelType enum.
|
||||
func (e NotificationChannelType) Valid() bool {
|
||||
switch e {
|
||||
case NotificationChannelTypeEmail:
|
||||
return true
|
||||
case NotificationChannelTypeWebhook:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Defines values for PeerNetworkRangeCheckAction.
|
||||
const (
|
||||
PeerNetworkRangeCheckActionAllow PeerNetworkRangeCheckAction = "allow"
|
||||
@@ -1893,6 +1912,12 @@ type EDRSentinelOneResponse struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// EmailTarget Target configuration for email notification channels.
|
||||
type EmailTarget struct {
|
||||
// Emails List of email addresses to send notifications to.
|
||||
Emails []openapi_types.Email `json:"emails"`
|
||||
}
|
||||
|
||||
// ErrorResponse Standard error response. Note: The exact structure of this error response is inferred from `util.WriteErrorResponse` and `util.WriteError` usage in the provided Go code, as a specific Go struct for errors was not provided.
|
||||
type ErrorResponse struct {
|
||||
// Message A human-readable error message.
|
||||
@@ -2666,6 +2691,67 @@ type NetworkTrafficUser struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// NotificationChannelRequest Request body for creating or updating a notification channel.
|
||||
type NotificationChannelRequest struct {
|
||||
// Enabled Whether this notification channel is active.
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// EventTypes List of activity event type codes this channel subscribes to.
|
||||
EventTypes []NotificationEventType `json:"event_types"`
|
||||
|
||||
// Target Channel-specific target configuration. The shape depends on the `type` field:
|
||||
// - `email`: requires an `EmailTarget` object
|
||||
// - `webhook`: requires a `WebhookTarget` object
|
||||
Target *NotificationChannelRequest_Target `json:"target,omitempty"`
|
||||
|
||||
// Type The type of notification channel.
|
||||
Type NotificationChannelType `json:"type"`
|
||||
}
|
||||
|
||||
// NotificationChannelRequest_Target Channel-specific target configuration. The shape depends on the `type` field:
|
||||
// - `email`: requires an `EmailTarget` object
|
||||
// - `webhook`: requires a `WebhookTarget` object
|
||||
type NotificationChannelRequest_Target struct {
|
||||
union json.RawMessage
|
||||
}
|
||||
|
||||
// NotificationChannelResponse A notification channel configuration.
|
||||
type NotificationChannelResponse struct {
|
||||
// Enabled Whether this notification channel is active.
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// EventTypes List of activity event type codes this channel subscribes to.
|
||||
EventTypes []NotificationEventType `json:"event_types"`
|
||||
|
||||
// Id Unique identifier of the notification channel.
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Target Channel-specific target configuration. The shape depends on the `type` field:
|
||||
// - `email`: an `EmailTarget` object
|
||||
// - `webhook`: a `WebhookTarget` object
|
||||
Target *NotificationChannelResponse_Target `json:"target,omitempty"`
|
||||
|
||||
// Type The type of notification channel.
|
||||
Type NotificationChannelType `json:"type"`
|
||||
}
|
||||
|
||||
// NotificationChannelResponse_Target Channel-specific target configuration. The shape depends on the `type` field:
|
||||
// - `email`: an `EmailTarget` object
|
||||
// - `webhook`: a `WebhookTarget` object
|
||||
type NotificationChannelResponse_Target struct {
|
||||
union json.RawMessage
|
||||
}
|
||||
|
||||
// NotificationChannelType The type of notification channel.
|
||||
type NotificationChannelType string
|
||||
|
||||
// NotificationEventType An activity event type code. See `GET /api/integrations/notifications/types` for the full list
|
||||
// of supported event types and their human-readable descriptions.
|
||||
type NotificationEventType = string
|
||||
|
||||
// NotificationTypeEntry A map of event type codes to their human-readable descriptions.
|
||||
type NotificationTypeEntry map[string]string
|
||||
|
||||
// OSVersionCheck Posture check for the version of operating system
|
||||
type OSVersionCheck struct {
|
||||
// Android Posture check for the version of operating system
|
||||
@@ -3406,6 +3492,9 @@ type ReverseProxyDomain struct {
|
||||
// Id Domain ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// RequireSubdomain Whether a subdomain label is required in front of this domain. When true, the domain cannot be used bare.
|
||||
RequireSubdomain *bool `json:"require_subdomain,omitempty"`
|
||||
|
||||
// SupportsCustomPorts Whether the cluster supports binding arbitrary TCP/UDP ports
|
||||
SupportsCustomPorts *bool `json:"supports_custom_ports,omitempty"`
|
||||
|
||||
@@ -3629,6 +3718,9 @@ type Service struct {
|
||||
|
||||
// Targets List of target backends for this service
|
||||
Targets []ServiceTarget `json:"targets"`
|
||||
|
||||
// Terminated Whether the service has been terminated. Terminated services cannot be updated. Services that violate the Terms of Service will be terminated.
|
||||
Terminated *bool `json:"terminated,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceMode Service mode. "http" for L7 reverse proxy, "tcp"/"udp"/"tls" for L4 passthrough.
|
||||
@@ -4208,6 +4300,16 @@ type UserRequest struct {
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
// WebhookTarget Target configuration for webhook notification channels.
|
||||
type WebhookTarget struct {
|
||||
// Headers Custom HTTP headers sent with each webhook request.
|
||||
// Values are write-only; in GET responses all values are masked.
|
||||
Headers *map[string]string `json:"headers,omitempty"`
|
||||
|
||||
// Url The webhook endpoint URL to send notifications to.
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
// WorkloadRequest defines model for WorkloadRequest.
|
||||
type WorkloadRequest struct {
|
||||
union json.RawMessage
|
||||
@@ -4561,6 +4663,12 @@ type PostApiIntegrationsMspTenantsIdSubscriptionJSONRequestBody PostApiIntegrati
|
||||
// PostApiIntegrationsMspTenantsIdUnlinkJSONRequestBody defines body for PostApiIntegrationsMspTenantsIdUnlink for application/json ContentType.
|
||||
type PostApiIntegrationsMspTenantsIdUnlinkJSONRequestBody PostApiIntegrationsMspTenantsIdUnlinkJSONBody
|
||||
|
||||
// CreateNotificationChannelJSONRequestBody defines body for CreateNotificationChannel for application/json ContentType.
|
||||
type CreateNotificationChannelJSONRequestBody = NotificationChannelRequest
|
||||
|
||||
// UpdateNotificationChannelJSONRequestBody defines body for UpdateNotificationChannel for application/json ContentType.
|
||||
type UpdateNotificationChannelJSONRequestBody = NotificationChannelRequest
|
||||
|
||||
// CreateSCIMIntegrationJSONRequestBody defines body for CreateSCIMIntegration for application/json ContentType.
|
||||
type CreateSCIMIntegrationJSONRequestBody = CreateScimIntegrationRequest
|
||||
|
||||
@@ -4657,6 +4765,130 @@ type PutApiUsersUserIdPasswordJSONRequestBody = PasswordChangeRequest
|
||||
// PostApiUsersUserIdTokensJSONRequestBody defines body for PostApiUsersUserIdTokens for application/json ContentType.
|
||||
type PostApiUsersUserIdTokensJSONRequestBody = PersonalAccessTokenRequest
|
||||
|
||||
// AsEmailTarget returns the union data inside the NotificationChannelRequest_Target as a EmailTarget
|
||||
func (t NotificationChannelRequest_Target) AsEmailTarget() (EmailTarget, error) {
|
||||
var body EmailTarget
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromEmailTarget overwrites any union data inside the NotificationChannelRequest_Target as the provided EmailTarget
|
||||
func (t *NotificationChannelRequest_Target) FromEmailTarget(v EmailTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeEmailTarget performs a merge with any union data inside the NotificationChannelRequest_Target, using the provided EmailTarget
|
||||
func (t *NotificationChannelRequest_Target) MergeEmailTarget(v EmailTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
// AsWebhookTarget returns the union data inside the NotificationChannelRequest_Target as a WebhookTarget
|
||||
func (t NotificationChannelRequest_Target) AsWebhookTarget() (WebhookTarget, error) {
|
||||
var body WebhookTarget
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromWebhookTarget overwrites any union data inside the NotificationChannelRequest_Target as the provided WebhookTarget
|
||||
func (t *NotificationChannelRequest_Target) FromWebhookTarget(v WebhookTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeWebhookTarget performs a merge with any union data inside the NotificationChannelRequest_Target, using the provided WebhookTarget
|
||||
func (t *NotificationChannelRequest_Target) MergeWebhookTarget(v WebhookTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
func (t NotificationChannelRequest_Target) MarshalJSON() ([]byte, error) {
|
||||
b, err := t.union.MarshalJSON()
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (t *NotificationChannelRequest_Target) UnmarshalJSON(b []byte) error {
|
||||
err := t.union.UnmarshalJSON(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// AsEmailTarget returns the union data inside the NotificationChannelResponse_Target as a EmailTarget
|
||||
func (t NotificationChannelResponse_Target) AsEmailTarget() (EmailTarget, error) {
|
||||
var body EmailTarget
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromEmailTarget overwrites any union data inside the NotificationChannelResponse_Target as the provided EmailTarget
|
||||
func (t *NotificationChannelResponse_Target) FromEmailTarget(v EmailTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeEmailTarget performs a merge with any union data inside the NotificationChannelResponse_Target, using the provided EmailTarget
|
||||
func (t *NotificationChannelResponse_Target) MergeEmailTarget(v EmailTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
// AsWebhookTarget returns the union data inside the NotificationChannelResponse_Target as a WebhookTarget
|
||||
func (t NotificationChannelResponse_Target) AsWebhookTarget() (WebhookTarget, error) {
|
||||
var body WebhookTarget
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromWebhookTarget overwrites any union data inside the NotificationChannelResponse_Target as the provided WebhookTarget
|
||||
func (t *NotificationChannelResponse_Target) FromWebhookTarget(v WebhookTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeWebhookTarget performs a merge with any union data inside the NotificationChannelResponse_Target, using the provided WebhookTarget
|
||||
func (t *NotificationChannelResponse_Target) MergeWebhookTarget(v WebhookTarget) error {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
func (t NotificationChannelResponse_Target) MarshalJSON() ([]byte, error) {
|
||||
b, err := t.union.MarshalJSON()
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (t *NotificationChannelResponse_Target) UnmarshalJSON(b []byte) error {
|
||||
err := t.union.UnmarshalJSON(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// AsBundleWorkloadRequest returns the union data inside the WorkloadRequest as a BundleWorkloadRequest
|
||||
func (t WorkloadRequest) AsBundleWorkloadRequest() (BundleWorkloadRequest, error) {
|
||||
var body BundleWorkloadRequest
|
||||
|
||||
@@ -181,8 +181,11 @@ type ProxyCapabilities struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Whether the proxy can bind arbitrary ports for TCP/UDP/TLS services.
|
||||
SupportsCustomPorts *bool `protobuf:"varint,1,opt,name=supports_custom_ports,json=supportsCustomPorts,proto3,oneof" json:"supports_custom_ports,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
// Whether the proxy requires a subdomain label in front of its cluster domain.
|
||||
// When true, tenants cannot use the cluster domain bare.
|
||||
RequireSubdomain *bool `protobuf:"varint,2,opt,name=require_subdomain,json=requireSubdomain,proto3,oneof" json:"require_subdomain,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ProxyCapabilities) Reset() {
|
||||
@@ -222,6 +225,13 @@ func (x *ProxyCapabilities) GetSupportsCustomPorts() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ProxyCapabilities) GetRequireSubdomain() bool {
|
||||
if x != nil && x.RequireSubdomain != nil {
|
||||
return *x.RequireSubdomain
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetMappingUpdateRequest is sent to initialise a mapping stream.
|
||||
type GetMappingUpdateRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@@ -1872,10 +1882,12 @@ var File_proxy_service_proto protoreflect.FileDescriptor
|
||||
const file_proxy_service_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x13proxy_service.proto\x12\n" +
|
||||
"management\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"f\n" +
|
||||
"management\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xae\x01\n" +
|
||||
"\x11ProxyCapabilities\x127\n" +
|
||||
"\x15supports_custom_ports\x18\x01 \x01(\bH\x00R\x13supportsCustomPorts\x88\x01\x01B\x18\n" +
|
||||
"\x16_supports_custom_ports\"\xe6\x01\n" +
|
||||
"\x15supports_custom_ports\x18\x01 \x01(\bH\x00R\x13supportsCustomPorts\x88\x01\x01\x120\n" +
|
||||
"\x11require_subdomain\x18\x02 \x01(\bH\x01R\x10requireSubdomain\x88\x01\x01B\x18\n" +
|
||||
"\x16_supports_custom_portsB\x14\n" +
|
||||
"\x12_require_subdomain\"\xe6\x01\n" +
|
||||
"\x17GetMappingUpdateRequest\x12\x19\n" +
|
||||
"\bproxy_id\x18\x01 \x01(\tR\aproxyId\x12\x18\n" +
|
||||
"\aversion\x18\x02 \x01(\tR\aversion\x129\n" +
|
||||
|
||||
@@ -31,6 +31,9 @@ service ProxyService {
|
||||
message ProxyCapabilities {
|
||||
// Whether the proxy can bind arbitrary ports for TCP/UDP/TLS services.
|
||||
optional bool supports_custom_ports = 1;
|
||||
// Whether the proxy requires a subdomain label in front of its cluster domain.
|
||||
// When true, accounts cannot use the cluster domain bare.
|
||||
optional bool require_subdomain = 2;
|
||||
}
|
||||
|
||||
// GetMappingUpdateRequest is sent to initialise a mapping stream.
|
||||
|
||||
Reference in New Issue
Block a user