) => {
+ e.target.select();
+ };
+
+ return (
+
+ {digits.map((digit, index) => (
+ {
+ inputRefs.current[index] = el;
+ }}
+ type="text"
+ inputMode="numeric"
+ maxLength={1}
+ value={digit}
+ onChange={(e) => handleChange(index, e.target.value)}
+ onKeyDown={(e) => handleKeyDown(index, e)}
+ onPaste={handlePaste}
+ onFocus={handleFocus}
+ disabled={disabled}
+ autoFocus={autoFocus && index === 0}
+ className={cn(
+ "flex-1 min-w-0 h-[42px] text-center text-sm rounded-md",
+ "dark:bg-nb-gray-900 border dark:border-nb-gray-700",
+ "dark:placeholder:text-neutral-400/70",
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
+ "ring-offset-neutral-200/20 dark:ring-offset-neutral-950/50 dark:focus-visible:ring-neutral-500/20",
+ "disabled:cursor-not-allowed disabled:opacity-40"
+ )}
+ />
+ ))}
+
+ );
+});
+
+export default PinCodeInput;
diff --git a/proxy/web/src/components/PoweredByNetBird.tsx b/proxy/web/src/components/PoweredByNetBird.tsx
new file mode 100644
index 000000000..555d8a79f
--- /dev/null
+++ b/proxy/web/src/components/PoweredByNetBird.tsx
@@ -0,0 +1,17 @@
+import { NetBirdLogo } from "./NetBirdLogo";
+
+export function PoweredByNetBird() {
+ return (
+
+
+ Powered by
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/proxy/web/src/components/SegmentedTabs.tsx b/proxy/web/src/components/SegmentedTabs.tsx
new file mode 100644
index 000000000..582b01f79
--- /dev/null
+++ b/proxy/web/src/components/SegmentedTabs.tsx
@@ -0,0 +1,145 @@
+import { cn } from "@/utils/helpers";
+import { useState, useMemo, useCallback } from "react";
+import { TabContext, useTabContext } from "./TabContext";
+
+type TabsProps = {
+ value?: string;
+ defaultValue?: string;
+ onChange?: (value: string) => void;
+ children:
+ | React.ReactNode
+ | ((context: { value: string; onChange: (value: string) => void }) => React.ReactNode);
+};
+
+function SegmentedTabs({ value, defaultValue, onChange, children }: Readonly) {
+ const [internalValue, setInternalValue] = useState(defaultValue ?? "");
+ const currentValue = value ?? internalValue;
+
+ const handleChange = useCallback((newValue: string) => {
+ if (value === undefined) {
+ setInternalValue(newValue);
+ }
+ onChange?.(newValue);
+ }, [value, onChange]);
+
+ const contextValue = useMemo(
+ () => ({ value: currentValue, onChange: handleChange }),
+ [currentValue, handleChange],
+ );
+
+ return (
+
+
+ {typeof children === "function"
+ ? children({ value: currentValue, onChange: handleChange })
+ : children}
+
+
+ );
+}
+
+function List({
+ children,
+ className,
+}: Readonly<{
+ children: React.ReactNode;
+ className?: string;
+}>) {
+ return (
+
+ {children}
+
+ );
+}
+
+function Trigger({
+ children,
+ value,
+ disabled = false,
+ className,
+ selected,
+ onClick,
+}: Readonly<{
+ children: React.ReactNode;
+ value: string;
+ disabled?: boolean;
+ className?: string;
+ selected?: boolean;
+ onClick?: () => void;
+}>) {
+ const context = useTabContext();
+ const isSelected = selected ?? value === context.value;
+
+ let stateClassName = "";
+ if (isSelected) {
+ stateClassName = "bg-nb-gray-900 text-white";
+ } else if (!disabled) {
+ stateClassName = "text-nb-gray-400 hover:bg-nb-gray-900/50";
+ }
+
+ const handleClick = () => {
+ context.onChange(value);
+ onClick?.();
+ };
+
+ return (
+
+ );
+}
+
+function Content({
+ children,
+ value,
+ className,
+ visible,
+}: Readonly<{
+ children: React.ReactNode;
+ value: string;
+ className?: string;
+ visible?: boolean;
+}>) {
+ const context = useTabContext();
+ const isVisible = visible ?? value === context.value;
+
+ if (!isVisible) return null;
+
+ return (
+
+ {children}
+
+ );
+}
+
+SegmentedTabs.List = List;
+SegmentedTabs.Trigger = Trigger;
+SegmentedTabs.Content = Content;
+
+export { SegmentedTabs };
diff --git a/proxy/web/src/components/Separator.tsx b/proxy/web/src/components/Separator.tsx
new file mode 100644
index 000000000..877c605cd
--- /dev/null
+++ b/proxy/web/src/components/Separator.tsx
@@ -0,0 +1,10 @@
+export const Separator = () => {
+ return (
+
+
+ OR
+
+
+
+ );
+};
diff --git a/proxy/web/src/components/StatusCard.tsx b/proxy/web/src/components/StatusCard.tsx
new file mode 100644
index 000000000..44ed957ee
--- /dev/null
+++ b/proxy/web/src/components/StatusCard.tsx
@@ -0,0 +1,38 @@
+import type { LucideIcon } from "lucide-react";
+import { ConnectionLine } from "./ConnectionLine";
+
+interface StatusCardProps {
+ icon: LucideIcon;
+ label: string;
+ detail?: string;
+ success?: boolean;
+ line?: boolean;
+}
+
+export function StatusCard({
+ icon: Icon,
+ label,
+ detail,
+ success = true,
+ line = true,
+}: Readonly) {
+ return (
+ <>
+ {line && }
+
+
+
+
+
{label}
+
+ {success ? "Connected" : "Unreachable"}
+
+ {detail && (
+
+ {detail}
+
+ )}
+
+ >
+ );
+}
diff --git a/proxy/web/src/components/TabContext.tsx b/proxy/web/src/components/TabContext.tsx
new file mode 100644
index 000000000..5a606ed49
--- /dev/null
+++ b/proxy/web/src/components/TabContext.tsx
@@ -0,0 +1,13 @@
+import { createContext, useContext } from "react";
+
+type TabContextValue = {
+ value: string;
+ onChange: (value: string) => void;
+};
+
+export const TabContext = createContext({
+ value: "",
+ onChange: () => {},
+});
+
+export const useTabContext = () => useContext(TabContext);
\ No newline at end of file
diff --git a/proxy/web/src/components/Title.tsx b/proxy/web/src/components/Title.tsx
new file mode 100644
index 000000000..1ed4a3b3b
--- /dev/null
+++ b/proxy/web/src/components/Title.tsx
@@ -0,0 +1,14 @@
+import { cn } from "@/utils/helpers";
+
+type Props = {
+ children: React.ReactNode;
+ className?: string;
+};
+
+export function Title({ children, className }: Readonly) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/proxy/web/src/data.ts b/proxy/web/src/data.ts
new file mode 100644
index 000000000..8f7eac58d
--- /dev/null
+++ b/proxy/web/src/data.ts
@@ -0,0 +1,54 @@
+// Auth method types matching Go
+export type AuthMethod = 'pin' | 'password' | 'oidc' | "link"
+
+// Page types
+export type PageType = 'auth' | 'error'
+
+// Error data structure
+export interface ErrorData {
+ code: number
+ title: string
+ message: string
+ proxy?: boolean
+ destination?: boolean
+ requestId?: string
+ simple?: boolean
+ retryUrl?: string
+}
+
+// Data injected by Go templates
+export interface Data {
+ page?: PageType
+ methods?: Partial>
+ error?: ErrorData
+}
+
+declare global {
+ // eslint-disable-next-line no-var
+ var __DATA__: Data | undefined
+}
+
+export function getData(): Data {
+ const data = globalThis.__DATA__ ?? {}
+
+ // Dev mode: allow ?page=error query param to preview error page
+ if (import.meta.env.DEV) {
+ const params = new URLSearchParams(globalThis.location.search)
+ const page = params.get('page')
+ if (page === 'error') {
+ return {
+ ...data,
+ page: 'error',
+ error: data.error ?? {
+ code: 503,
+ title: 'Service Unavailable',
+ message: 'The service you are trying to access is temporarily unavailable. Please try again later.',
+ proxy: true,
+ destination: false,
+ },
+ }
+ }
+ }
+
+ return data
+}
diff --git a/proxy/web/src/index.css b/proxy/web/src/index.css
new file mode 100644
index 000000000..ad011f525
--- /dev/null
+++ b/proxy/web/src/index.css
@@ -0,0 +1,213 @@
+@import "tailwindcss";
+
+@custom-variant dark (&:where(.dark, .dark *));
+
+@font-face {
+ font-family: "Inter";
+ font-style: normal;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url("./assets/fonts/Inter-VariableFont_opsz,wght.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: "Inter";
+ font-style: italic;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url("./assets/fonts/Inter-Italic-VariableFont_opsz,wght.ttf") format("truetype");
+}
+
+@theme {
+ /* Gray */
+ --color-gray-50: #F9FAFB;
+ --color-gray-100: #F3F4F6;
+ --color-gray-200: #E5E7EB;
+ --color-gray-300: #D1D5DB;
+ --color-gray-400: #9CA3AF;
+ --color-gray-500: #6B7280;
+ --color-gray-600: #4B5563;
+ --color-gray-700: #374151;
+ --color-gray-800: #1F2937;
+ --color-gray-900: #111827;
+
+ /* Red */
+ --color-red-50: #FDF2F2;
+ --color-red-100: #FDE8E8;
+ --color-red-200: #FBD5D5;
+ --color-red-300: #F8B4B4;
+ --color-red-400: #F98080;
+ --color-red-500: #F05252;
+ --color-red-600: #E02424;
+ --color-red-700: #C81E1E;
+ --color-red-800: #9B1C1C;
+ --color-red-900: #771D1D;
+
+ /* Yellow */
+ --color-yellow-50: #FDFDEA;
+ --color-yellow-100: #FDF6B2;
+ --color-yellow-200: #FCE96A;
+ --color-yellow-300: #FACA15;
+ --color-yellow-400: #E3A008;
+ --color-yellow-500: #C27803;
+ --color-yellow-600: #9F580A;
+ --color-yellow-700: #8E4B10;
+ --color-yellow-800: #723B13;
+ --color-yellow-900: #633112;
+
+ /* Green */
+ --color-green-50: #F3FAF7;
+ --color-green-100: #DEF7EC;
+ --color-green-200: #BCF0DA;
+ --color-green-300: #84E1BC;
+ --color-green-400: #31C48D;
+ --color-green-500: #0E9F6E;
+ --color-green-600: #057A55;
+ --color-green-700: #046C4E;
+ --color-green-800: #03543F;
+ --color-green-900: #014737;
+
+ /* Blue */
+ --color-blue-50: #EBF5FF;
+ --color-blue-100: #E1EFFE;
+ --color-blue-200: #C3DDFD;
+ --color-blue-300: #A4CAFE;
+ --color-blue-400: #76A9FA;
+ --color-blue-500: #3F83F8;
+ --color-blue-600: #1C64F2;
+ --color-blue-700: #1A56DB;
+ --color-blue-800: #1E429F;
+ --color-blue-900: #233876;
+
+ /* Indigo */
+ --color-indigo-50: #F0F5FF;
+ --color-indigo-100: #E5EDFF;
+ --color-indigo-200: #CDDBFE;
+ --color-indigo-300: #B4C6FC;
+ --color-indigo-400: #8DA2FB;
+ --color-indigo-500: #6875F5;
+ --color-indigo-600: #5850EC;
+ --color-indigo-700: #5145CD;
+ --color-indigo-800: #42389D;
+ --color-indigo-900: #362F78;
+
+ /* Purple */
+ --color-purple-50: #F6F5FF;
+ --color-purple-100: #EDEBFE;
+ --color-purple-200: #DCD7FE;
+ --color-purple-300: #CABFFD;
+ --color-purple-400: #AC94FA;
+ --color-purple-500: #9061F9;
+ --color-purple-600: #7E3AF2;
+ --color-purple-700: #6C2BD9;
+ --color-purple-800: #5521B5;
+ --color-purple-900: #4A1D96;
+
+ /* Pink */
+ --color-pink-50: #FDF2F8;
+ --color-pink-100: #FCE8F3;
+ --color-pink-200: #FAD1E8;
+ --color-pink-300: #F8B4D9;
+ --color-pink-400: #F17EB8;
+ --color-pink-500: #E74694;
+ --color-pink-600: #D61F69;
+ --color-pink-700: #BF125D;
+ --color-pink-800: #99154B;
+ --color-pink-900: #751A3D;
+
+ /* NetBird Gray */
+ --color-nb-gray: #181A1D;
+ --color-nb-gray-50: #f4f6f7;
+ --color-nb-gray-100: #e4e7e9;
+ --color-nb-gray-200: #cbd2d6;
+ --color-nb-gray-250: #b7c0c6;
+ --color-nb-gray-300: #aab4bd;
+ --color-nb-gray-350: #8f9ca8;
+ --color-nb-gray-400: #7c8994;
+ --color-nb-gray-500: #616e79;
+ --color-nb-gray-600: #535d67;
+ --color-nb-gray-700: #474e57;
+ --color-nb-gray-800: #3f444b;
+ --color-nb-gray-850: #363b40;
+ --color-nb-gray-900: #32363D;
+ --color-nb-gray-910: #2b2f33;
+ --color-nb-gray-920: #25282d;
+ --color-nb-gray-925: #1e2123;
+ --color-nb-gray-930: #25282c;
+ --color-nb-gray-935: #1f2124;
+ --color-nb-gray-940: #1c1e21;
+ --color-nb-gray-950: #181a1d;
+ --color-nb-gray-960: #15171a;
+
+ /* NetBird Orange */
+ --color-netbird: #f68330;
+ --color-netbird-50: #fff6ed;
+ --color-netbird-100: #feecd6;
+ --color-netbird-150: #ffdfb8;
+ --color-netbird-200: #ffd4a6;
+ --color-netbird-300: #fab677;
+ --color-netbird-400: #f68330;
+ --color-netbird-500: #f46d1b;
+ --color-netbird-600: #e55311;
+ --color-netbird-700: #be3e10;
+ --color-netbird-800: #973215;
+ --color-netbird-900: #7a2b14;
+ --color-netbird-950: #421308;
+
+ /* NetBird Blue */
+ --color-nb-blue: #31e4f5;
+ --color-nb-blue-50: #ebffff;
+ --color-nb-blue-100: #cefdff;
+ --color-nb-blue-200: #a2f9ff;
+ --color-nb-blue-300: #63f2fd;
+ --color-nb-blue-400: #31e4f5;
+ --color-nb-blue-500: #00c4da;
+ --color-nb-blue-600: #039cb7;
+ --color-nb-blue-700: #0a7c94;
+ --color-nb-blue-800: #126478;
+ --color-nb-blue-900: #145365;
+ --color-nb-blue-950: #063746;
+}
+
+:root {
+ --nb-bg: #18191d;
+ --nb-card-bg: #1b1f22;
+ --nb-border: rgba(50, 54, 61, 0.5);
+ --nb-text: #e4e7e9;
+ --nb-text-muted: rgba(167, 177, 185, 0.8);
+ --nb-primary: #f68330;
+ --nb-primary-hover: #e5722a;
+ --nb-input-bg: rgba(63, 68, 75, 0.5);
+ --nb-input-border: rgba(63, 68, 75, 0.8);
+ --nb-error-bg: rgba(153, 27, 27, 0.2);
+ --nb-error-border: rgba(153, 27, 27, 0.5);
+ --nb-error-text: #f87171;
+}
+
+html {
+ color-scheme: dark;
+ @apply bg-nb-gray;
+}
+
+html.dark,
+:root {
+ color-scheme: dark;
+}
+
+body {
+ font-family: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+}
+
+h1 {
+ @apply text-2xl font-medium text-gray-700 dark:text-nb-gray-100 my-1;
+}
+h2 {
+ @apply text-xl font-medium text-gray-700 dark:text-nb-gray-100 my-1;
+}
+p {
+ @apply font-light tracking-wide text-gray-700 dark:text-zinc-50 text-sm;
+}
+
+[placeholder] {
+ text-overflow: ellipsis;
+}
diff --git a/proxy/web/src/main.tsx b/proxy/web/src/main.tsx
new file mode 100644
index 000000000..e836cc12b
--- /dev/null
+++ b/proxy/web/src/main.tsx
@@ -0,0 +1,18 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+import { ErrorPage } from './ErrorPage.tsx'
+import { getData } from '@/data'
+
+const data = getData()
+
+createRoot(document.getElementById('root')!).render(
+
+ {data.page === 'error' && data.error ? (
+
+ ) : (
+
+ )}
+ ,
+)
diff --git a/proxy/web/src/utils/helpers.ts b/proxy/web/src/utils/helpers.ts
new file mode 100644
index 000000000..a5ef19350
--- /dev/null
+++ b/proxy/web/src/utils/helpers.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/proxy/web/src/vite-env.d.ts b/proxy/web/src/vite-env.d.ts
new file mode 100644
index 000000000..ddeb09246
--- /dev/null
+++ b/proxy/web/src/vite-env.d.ts
@@ -0,0 +1,6 @@
+///
+
+declare module "*.svg" {
+ const content: string;
+ export default content;
+}
\ No newline at end of file
diff --git a/proxy/web/tsconfig.json b/proxy/web/tsconfig.json
new file mode 100644
index 000000000..5a060c775
--- /dev/null
+++ b/proxy/web/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ },
+ "include": ["src", "vite.config.ts"]
+}
diff --git a/proxy/web/vite.config.ts b/proxy/web/vite.config.ts
new file mode 100644
index 000000000..a5f9ee2a8
--- /dev/null
+++ b/proxy/web/vite.config.ts
@@ -0,0 +1,32 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import tailwindcss from '@tailwindcss/vite'
+import path from 'node:path'
+
+export default defineConfig({
+ plugins: [react(), tailwindcss()],
+ base: '/__netbird__/',
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+ server: {
+ port: 3031,
+ },
+ preview: {
+ port: 3031,
+ },
+ build: {
+ outDir: 'dist',
+ assetsDir: 'assets',
+ cssCodeSplit: false,
+ rollupOptions: {
+ output: {
+ entryFileNames: 'assets/index.js',
+ chunkFileNames: 'assets/[name].js',
+ assetFileNames: 'assets/[name][extname]',
+ },
+ },
+ },
+})
diff --git a/proxy/web/web.go b/proxy/web/web.go
new file mode 100644
index 000000000..6773a9c1a
--- /dev/null
+++ b/proxy/web/web.go
@@ -0,0 +1,189 @@
+package web
+
+import (
+ "bytes"
+ "embed"
+ "encoding/json"
+ "html/template"
+ "io/fs"
+ "net/http"
+ "net/url"
+ "path/filepath"
+ "strings"
+)
+
+// PathPrefix is the unique URL prefix for serving the proxy's own web assets.
+// Using a distinctive prefix prevents collisions with backend application routes.
+const PathPrefix = "/__netbird__"
+
+//go:embed dist/*
+var files embed.FS
+
+var (
+ webFS fs.FS
+ tmpl *template.Template
+ initErr error
+)
+
+func init() {
+ webFS, initErr = fs.Sub(files, "dist")
+ if initErr != nil {
+ return
+ }
+
+ var indexHTML []byte
+ indexHTML, initErr = fs.ReadFile(webFS, "index.html")
+ if initErr != nil {
+ return
+ }
+
+ tmpl, initErr = template.New("index").Parse(string(indexHTML))
+}
+
+// AssetHandler returns middleware that intercepts requests for the proxy's
+// own web assets (under PathPrefix) and serves them from the embedded
+// filesystem, preventing them from being forwarded to backend services.
+func AssetHandler(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if strings.HasPrefix(r.URL.Path, PathPrefix+"/") {
+ serveAsset(w, r)
+ return
+ }
+ next.ServeHTTP(w, r)
+ })
+}
+
+// serveAsset serves a static file from the embedded filesystem.
+func serveAsset(w http.ResponseWriter, r *http.Request) {
+ if initErr != nil {
+ http.Error(w, initErr.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // Strip the prefix to get the embedded FS path (e.g. "assets/index.js").
+ filePath := strings.TrimPrefix(r.URL.Path, PathPrefix+"/")
+ content, err := fs.ReadFile(webFS, filePath)
+ if err != nil {
+ http.Error(w, "not found", http.StatusNotFound)
+ return
+ }
+
+ setContentType(w, filePath)
+ w.Write(content) //nolint:errcheck
+}
+
+// ServeHTTP serves the web UI. For static assets it serves them directly,
+// for other paths it renders the page with the provided data.
+// Optional statusCode can be passed to set a custom HTTP status code (default 200).
+func ServeHTTP(w http.ResponseWriter, r *http.Request, data any, statusCode ...int) {
+ if initErr != nil {
+ http.Error(w, initErr.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ path := r.URL.Path
+
+ // Serve robots.txt
+ if path == "/robots.txt" {
+ content, err := fs.ReadFile(webFS, "robots.txt")
+ if err != nil {
+ http.Error(w, "not found", http.StatusNotFound)
+ return
+ }
+ w.Header().Set("Content-Type", "text/plain")
+ w.Write(content) //nolint:errcheck
+ return
+ }
+
+ // Serve static assets directly (handles requests that reach here
+ // via auth middleware calling ServeHTTP for unauthenticated requests).
+ if strings.HasPrefix(path, PathPrefix+"/") {
+ serveAsset(w, r)
+ return
+ }
+
+ // Render the page with data
+ dataJSON, _ := json.Marshal(data) //nolint:errcheck
+
+ var buf bytes.Buffer
+ if err := tmpl.Execute(&buf, struct {
+ Data template.JS
+ }{
+ Data: template.JS(dataJSON), //nolint:gosec
+ }); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "text/html")
+ if len(statusCode) > 0 {
+ w.WriteHeader(statusCode[0])
+ }
+ w.Write(buf.Bytes()) //nolint:errcheck
+}
+
+func setContentType(w http.ResponseWriter, filePath string) {
+ switch filepath.Ext(filePath) {
+ case ".js":
+ w.Header().Set("Content-Type", "application/javascript")
+ case ".css":
+ w.Header().Set("Content-Type", "text/css")
+ case ".svg":
+ w.Header().Set("Content-Type", "image/svg+xml")
+ case ".ttf":
+ w.Header().Set("Content-Type", "font/ttf")
+ case ".woff":
+ w.Header().Set("Content-Type", "font/woff")
+ case ".woff2":
+ w.Header().Set("Content-Type", "font/woff2")
+ case ".ico":
+ w.Header().Set("Content-Type", "image/x-icon")
+ }
+}
+
+// ErrorStatus represents the connection status for each component in the error page.
+type ErrorStatus struct {
+ Proxy bool
+ Destination bool
+}
+
+// ServeErrorPage renders a user-friendly error page with the given details.
+func ServeErrorPage(w http.ResponseWriter, r *http.Request, code int, title, message, requestID string, status ErrorStatus) {
+ ServeHTTP(w, r, map[string]any{
+ "page": "error",
+ "error": map[string]any{
+ "code": code,
+ "title": title,
+ "message": message,
+ "proxy": status.Proxy,
+ "destination": status.Destination,
+ "requestId": requestID,
+ },
+ }, code)
+}
+
+// ServeAccessDeniedPage renders a simple access denied page without the connection status graph.
+func ServeAccessDeniedPage(w http.ResponseWriter, r *http.Request, code int, title, message, requestID string) {
+ ServeHTTP(w, r, map[string]any{
+ "page": "error",
+ "error": map[string]any{
+ "code": code,
+ "title": title,
+ "message": message,
+ "requestId": requestID,
+ "simple": true,
+ "retryUrl": stripAuthParams(r.URL),
+ },
+ }, code)
+}
+
+// stripAuthParams returns the request URI with auth-related query parameters removed.
+func stripAuthParams(u *url.URL) string {
+ q := u.Query()
+ q.Del("session_token")
+ q.Del("error")
+ q.Del("error_description")
+ clean := *u
+ clean.RawQuery = q.Encode()
+ return clean.RequestURI()
+}
diff --git a/shared/hash/argon2id/argon2id.go b/shared/hash/argon2id/argon2id.go
new file mode 100644
index 000000000..8d493aaba
--- /dev/null
+++ b/shared/hash/argon2id/argon2id.go
@@ -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
+}
diff --git a/shared/hash/argon2id/argon2id_test.go b/shared/hash/argon2id/argon2id_test.go
new file mode 100644
index 000000000..f907a1687
--- /dev/null
+++ b/shared/hash/argon2id/argon2id_test.go
@@ -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)
+ }
+}
diff --git a/shared/management/http/api/openapi.yml b/shared/management/http/api/openapi.yml
index 5a504c471..1f4a163e5 100644
--- a/shared/management/http/api/openapi.yml
+++ b/shared/management/http/api/openapi.yml
@@ -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"
diff --git a/shared/management/http/api/types.gen.go b/shared/management/http/api/types.gen.go
index 3f16af46b..7a7e75855 100644
--- a/shared/management/http/api/types.gen.go
+++ b/shared/management/http/api/types.gen.go
@@ -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
diff --git a/shared/management/proto/generate.sh b/shared/management/proto/generate.sh
index 207630ae7..7cb0f75a5 100755
--- a/shared/management/proto/generate.sh
+++ b/shared/management/proto/generate.sh
@@ -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"
diff --git a/shared/management/proto/management.pb.go b/shared/management/proto/management.pb.go
index dfa9adaf6..44838fc16 100644
--- a/shared/management/proto/management.pb.go
+++ b/shared/management/proto/management.pb.go
@@ -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
diff --git a/shared/management/proto/proxy_service.pb.go b/shared/management/proto/proxy_service.pb.go
new file mode 100644
index 000000000..13fcb159e
--- /dev/null
+++ b/shared/management/proto/proxy_service.pb.go
@@ -0,0 +1,2061 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.26.0
+// protoc v6.33.0
+// source: proxy_service.proto
+
+package proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ProxyMappingUpdateType int32
+
+const (
+ ProxyMappingUpdateType_UPDATE_TYPE_CREATED ProxyMappingUpdateType = 0
+ ProxyMappingUpdateType_UPDATE_TYPE_MODIFIED ProxyMappingUpdateType = 1
+ ProxyMappingUpdateType_UPDATE_TYPE_REMOVED ProxyMappingUpdateType = 2
+)
+
+// Enum value maps for ProxyMappingUpdateType.
+var (
+ ProxyMappingUpdateType_name = map[int32]string{
+ 0: "UPDATE_TYPE_CREATED",
+ 1: "UPDATE_TYPE_MODIFIED",
+ 2: "UPDATE_TYPE_REMOVED",
+ }
+ ProxyMappingUpdateType_value = map[string]int32{
+ "UPDATE_TYPE_CREATED": 0,
+ "UPDATE_TYPE_MODIFIED": 1,
+ "UPDATE_TYPE_REMOVED": 2,
+ }
+)
+
+func (x ProxyMappingUpdateType) Enum() *ProxyMappingUpdateType {
+ p := new(ProxyMappingUpdateType)
+ *p = x
+ return p
+}
+
+func (x ProxyMappingUpdateType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ProxyMappingUpdateType) Descriptor() protoreflect.EnumDescriptor {
+ return file_proxy_service_proto_enumTypes[0].Descriptor()
+}
+
+func (ProxyMappingUpdateType) Type() protoreflect.EnumType {
+ return &file_proxy_service_proto_enumTypes[0]
+}
+
+func (x ProxyMappingUpdateType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ProxyMappingUpdateType.Descriptor instead.
+func (ProxyMappingUpdateType) EnumDescriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{0}
+}
+
+type ProxyStatus int32
+
+const (
+ ProxyStatus_PROXY_STATUS_PENDING ProxyStatus = 0
+ ProxyStatus_PROXY_STATUS_ACTIVE ProxyStatus = 1
+ ProxyStatus_PROXY_STATUS_TUNNEL_NOT_CREATED ProxyStatus = 2
+ ProxyStatus_PROXY_STATUS_CERTIFICATE_PENDING ProxyStatus = 3
+ ProxyStatus_PROXY_STATUS_CERTIFICATE_FAILED ProxyStatus = 4
+ ProxyStatus_PROXY_STATUS_ERROR ProxyStatus = 5
+)
+
+// Enum value maps for ProxyStatus.
+var (
+ ProxyStatus_name = map[int32]string{
+ 0: "PROXY_STATUS_PENDING",
+ 1: "PROXY_STATUS_ACTIVE",
+ 2: "PROXY_STATUS_TUNNEL_NOT_CREATED",
+ 3: "PROXY_STATUS_CERTIFICATE_PENDING",
+ 4: "PROXY_STATUS_CERTIFICATE_FAILED",
+ 5: "PROXY_STATUS_ERROR",
+ }
+ ProxyStatus_value = map[string]int32{
+ "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,
+ }
+)
+
+func (x ProxyStatus) Enum() *ProxyStatus {
+ p := new(ProxyStatus)
+ *p = x
+ return p
+}
+
+func (x ProxyStatus) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ProxyStatus) Descriptor() protoreflect.EnumDescriptor {
+ return file_proxy_service_proto_enumTypes[1].Descriptor()
+}
+
+func (ProxyStatus) Type() protoreflect.EnumType {
+ return &file_proxy_service_proto_enumTypes[1]
+}
+
+func (x ProxyStatus) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ProxyStatus.Descriptor instead.
+func (ProxyStatus) EnumDescriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{1}
+}
+
+// GetMappingUpdateRequest is sent to initialise a mapping stream.
+type GetMappingUpdateRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ProxyId string `protobuf:"bytes,1,opt,name=proxy_id,json=proxyId,proto3" json:"proxy_id,omitempty"`
+ Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+ StartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"`
+ Address string `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"`
+}
+
+func (x *GetMappingUpdateRequest) Reset() {
+ *x = GetMappingUpdateRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetMappingUpdateRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetMappingUpdateRequest) ProtoMessage() {}
+
+func (x *GetMappingUpdateRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetMappingUpdateRequest.ProtoReflect.Descriptor instead.
+func (*GetMappingUpdateRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *GetMappingUpdateRequest) GetProxyId() string {
+ if x != nil {
+ return x.ProxyId
+ }
+ return ""
+}
+
+func (x *GetMappingUpdateRequest) GetVersion() string {
+ if x != nil {
+ return x.Version
+ }
+ return ""
+}
+
+func (x *GetMappingUpdateRequest) GetStartedAt() *timestamppb.Timestamp {
+ if x != nil {
+ return x.StartedAt
+ }
+ return nil
+}
+
+func (x *GetMappingUpdateRequest) GetAddress() string {
+ if x != nil {
+ return x.Address
+ }
+ return ""
+}
+
+// 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.
+type GetMappingUpdateResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Mapping []*ProxyMapping `protobuf:"bytes,1,rep,name=mapping,proto3" json:"mapping,omitempty"`
+ // initial_sync_complete is set on the last message of the initial snapshot.
+ // The proxy uses this to signal that startup is complete.
+ InitialSyncComplete bool `protobuf:"varint,2,opt,name=initial_sync_complete,json=initialSyncComplete,proto3" json:"initial_sync_complete,omitempty"`
+}
+
+func (x *GetMappingUpdateResponse) Reset() {
+ *x = GetMappingUpdateResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetMappingUpdateResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetMappingUpdateResponse) ProtoMessage() {}
+
+func (x *GetMappingUpdateResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetMappingUpdateResponse.ProtoReflect.Descriptor instead.
+func (*GetMappingUpdateResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *GetMappingUpdateResponse) GetMapping() []*ProxyMapping {
+ if x != nil {
+ return x.Mapping
+ }
+ return nil
+}
+
+func (x *GetMappingUpdateResponse) GetInitialSyncComplete() bool {
+ if x != nil {
+ return x.InitialSyncComplete
+ }
+ return false
+}
+
+type PathMapping struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
+ Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
+}
+
+func (x *PathMapping) Reset() {
+ *x = PathMapping{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PathMapping) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PathMapping) ProtoMessage() {}
+
+func (x *PathMapping) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PathMapping.ProtoReflect.Descriptor instead.
+func (*PathMapping) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *PathMapping) GetPath() string {
+ if x != nil {
+ return x.Path
+ }
+ return ""
+}
+
+func (x *PathMapping) GetTarget() string {
+ if x != nil {
+ return x.Target
+ }
+ return ""
+}
+
+type Authentication struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SessionKey string `protobuf:"bytes,1,opt,name=session_key,json=sessionKey,proto3" json:"session_key,omitempty"`
+ MaxSessionAgeSeconds int64 `protobuf:"varint,2,opt,name=max_session_age_seconds,json=maxSessionAgeSeconds,proto3" json:"max_session_age_seconds,omitempty"`
+ Password bool `protobuf:"varint,3,opt,name=password,proto3" json:"password,omitempty"`
+ Pin bool `protobuf:"varint,4,opt,name=pin,proto3" json:"pin,omitempty"`
+ Oidc bool `protobuf:"varint,5,opt,name=oidc,proto3" json:"oidc,omitempty"`
+}
+
+func (x *Authentication) Reset() {
+ *x = Authentication{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Authentication) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Authentication) ProtoMessage() {}
+
+func (x *Authentication) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Authentication.ProtoReflect.Descriptor instead.
+func (*Authentication) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Authentication) GetSessionKey() string {
+ if x != nil {
+ return x.SessionKey
+ }
+ return ""
+}
+
+func (x *Authentication) GetMaxSessionAgeSeconds() int64 {
+ if x != nil {
+ return x.MaxSessionAgeSeconds
+ }
+ return 0
+}
+
+func (x *Authentication) GetPassword() bool {
+ if x != nil {
+ return x.Password
+ }
+ return false
+}
+
+func (x *Authentication) GetPin() bool {
+ if x != nil {
+ return x.Pin
+ }
+ return false
+}
+
+func (x *Authentication) GetOidc() bool {
+ if x != nil {
+ return x.Oidc
+ }
+ return false
+}
+
+type ProxyMapping struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type ProxyMappingUpdateType `protobuf:"varint,1,opt,name=type,proto3,enum=management.ProxyMappingUpdateType" json:"type,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ Domain string `protobuf:"bytes,4,opt,name=domain,proto3" json:"domain,omitempty"`
+ Path []*PathMapping `protobuf:"bytes,5,rep,name=path,proto3" json:"path,omitempty"`
+ AuthToken string `protobuf:"bytes,6,opt,name=auth_token,json=authToken,proto3" json:"auth_token,omitempty"`
+ Auth *Authentication `protobuf:"bytes,7,opt,name=auth,proto3" json:"auth,omitempty"`
+ // 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.
+ PassHostHeader bool `protobuf:"varint,8,opt,name=pass_host_header,json=passHostHeader,proto3" json:"pass_host_header,omitempty"`
+ // When true, Location headers in backend responses are rewritten to replace
+ // the backend address with the public-facing domain.
+ RewriteRedirects bool `protobuf:"varint,9,opt,name=rewrite_redirects,json=rewriteRedirects,proto3" json:"rewrite_redirects,omitempty"`
+}
+
+func (x *ProxyMapping) Reset() {
+ *x = ProxyMapping{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ProxyMapping) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ProxyMapping) ProtoMessage() {}
+
+func (x *ProxyMapping) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ProxyMapping.ProtoReflect.Descriptor instead.
+func (*ProxyMapping) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ProxyMapping) GetType() ProxyMappingUpdateType {
+ if x != nil {
+ return x.Type
+ }
+ return ProxyMappingUpdateType_UPDATE_TYPE_CREATED
+}
+
+func (x *ProxyMapping) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *ProxyMapping) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (x *ProxyMapping) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *ProxyMapping) GetPath() []*PathMapping {
+ if x != nil {
+ return x.Path
+ }
+ return nil
+}
+
+func (x *ProxyMapping) GetAuthToken() string {
+ if x != nil {
+ return x.AuthToken
+ }
+ return ""
+}
+
+func (x *ProxyMapping) GetAuth() *Authentication {
+ if x != nil {
+ return x.Auth
+ }
+ return nil
+}
+
+func (x *ProxyMapping) GetPassHostHeader() bool {
+ if x != nil {
+ return x.PassHostHeader
+ }
+ return false
+}
+
+func (x *ProxyMapping) GetRewriteRedirects() bool {
+ if x != nil {
+ return x.RewriteRedirects
+ }
+ return false
+}
+
+// SendAccessLogRequest consists of one or more AccessLogs from a Proxy.
+type SendAccessLogRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Log *AccessLog `protobuf:"bytes,1,opt,name=log,proto3" json:"log,omitempty"`
+}
+
+func (x *SendAccessLogRequest) Reset() {
+ *x = SendAccessLogRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SendAccessLogRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendAccessLogRequest) ProtoMessage() {}
+
+func (x *SendAccessLogRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SendAccessLogRequest.ProtoReflect.Descriptor instead.
+func (*SendAccessLogRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *SendAccessLogRequest) GetLog() *AccessLog {
+ if x != nil {
+ return x.Log
+ }
+ return nil
+}
+
+// SendAccessLogResponse is intentionally empty to allow for future expansion.
+type SendAccessLogResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *SendAccessLogResponse) Reset() {
+ *x = SendAccessLogResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SendAccessLogResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendAccessLogResponse) ProtoMessage() {}
+
+func (x *SendAccessLogResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SendAccessLogResponse.ProtoReflect.Descriptor instead.
+func (*SendAccessLogResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{6}
+}
+
+type AccessLog struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ LogId string `protobuf:"bytes,2,opt,name=log_id,json=logId,proto3" json:"log_id,omitempty"`
+ AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
+ Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host,omitempty"`
+ Path string `protobuf:"bytes,6,opt,name=path,proto3" json:"path,omitempty"`
+ DurationMs int64 `protobuf:"varint,7,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"`
+ Method string `protobuf:"bytes,8,opt,name=method,proto3" json:"method,omitempty"`
+ ResponseCode int32 `protobuf:"varint,9,opt,name=response_code,json=responseCode,proto3" json:"response_code,omitempty"`
+ SourceIp string `protobuf:"bytes,10,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"`
+ AuthMechanism string `protobuf:"bytes,11,opt,name=auth_mechanism,json=authMechanism,proto3" json:"auth_mechanism,omitempty"`
+ UserId string `protobuf:"bytes,12,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
+ AuthSuccess bool `protobuf:"varint,13,opt,name=auth_success,json=authSuccess,proto3" json:"auth_success,omitempty"`
+}
+
+func (x *AccessLog) Reset() {
+ *x = AccessLog{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AccessLog) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AccessLog) ProtoMessage() {}
+
+func (x *AccessLog) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AccessLog.ProtoReflect.Descriptor instead.
+func (*AccessLog) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *AccessLog) GetTimestamp() *timestamppb.Timestamp {
+ if x != nil {
+ return x.Timestamp
+ }
+ return nil
+}
+
+func (x *AccessLog) GetLogId() string {
+ if x != nil {
+ return x.LogId
+ }
+ return ""
+}
+
+func (x *AccessLog) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (x *AccessLog) GetServiceId() string {
+ if x != nil {
+ return x.ServiceId
+ }
+ return ""
+}
+
+func (x *AccessLog) GetHost() string {
+ if x != nil {
+ return x.Host
+ }
+ return ""
+}
+
+func (x *AccessLog) GetPath() string {
+ if x != nil {
+ return x.Path
+ }
+ return ""
+}
+
+func (x *AccessLog) GetDurationMs() int64 {
+ if x != nil {
+ return x.DurationMs
+ }
+ return 0
+}
+
+func (x *AccessLog) GetMethod() string {
+ if x != nil {
+ return x.Method
+ }
+ return ""
+}
+
+func (x *AccessLog) GetResponseCode() int32 {
+ if x != nil {
+ return x.ResponseCode
+ }
+ return 0
+}
+
+func (x *AccessLog) GetSourceIp() string {
+ if x != nil {
+ return x.SourceIp
+ }
+ return ""
+}
+
+func (x *AccessLog) GetAuthMechanism() string {
+ if x != nil {
+ return x.AuthMechanism
+ }
+ return ""
+}
+
+func (x *AccessLog) GetUserId() string {
+ if x != nil {
+ return x.UserId
+ }
+ return ""
+}
+
+func (x *AccessLog) GetAuthSuccess() bool {
+ if x != nil {
+ return x.AuthSuccess
+ }
+ return false
+}
+
+type AuthenticateRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ // Types that are assignable to Request:
+ //
+ // *AuthenticateRequest_Password
+ // *AuthenticateRequest_Pin
+ Request isAuthenticateRequest_Request `protobuf_oneof:"request"`
+}
+
+func (x *AuthenticateRequest) Reset() {
+ *x = AuthenticateRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AuthenticateRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AuthenticateRequest) ProtoMessage() {}
+
+func (x *AuthenticateRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AuthenticateRequest.ProtoReflect.Descriptor instead.
+func (*AuthenticateRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *AuthenticateRequest) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *AuthenticateRequest) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (m *AuthenticateRequest) GetRequest() isAuthenticateRequest_Request {
+ if m != nil {
+ return m.Request
+ }
+ return nil
+}
+
+func (x *AuthenticateRequest) GetPassword() *PasswordRequest {
+ if x, ok := x.GetRequest().(*AuthenticateRequest_Password); ok {
+ return x.Password
+ }
+ return nil
+}
+
+func (x *AuthenticateRequest) GetPin() *PinRequest {
+ if x, ok := x.GetRequest().(*AuthenticateRequest_Pin); ok {
+ return x.Pin
+ }
+ return nil
+}
+
+type isAuthenticateRequest_Request interface {
+ isAuthenticateRequest_Request()
+}
+
+type AuthenticateRequest_Password struct {
+ Password *PasswordRequest `protobuf:"bytes,3,opt,name=password,proto3,oneof"`
+}
+
+type AuthenticateRequest_Pin struct {
+ Pin *PinRequest `protobuf:"bytes,4,opt,name=pin,proto3,oneof"`
+}
+
+func (*AuthenticateRequest_Password) isAuthenticateRequest_Request() {}
+
+func (*AuthenticateRequest_Pin) isAuthenticateRequest_Request() {}
+
+type PasswordRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
+}
+
+func (x *PasswordRequest) Reset() {
+ *x = PasswordRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PasswordRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PasswordRequest) ProtoMessage() {}
+
+func (x *PasswordRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PasswordRequest.ProtoReflect.Descriptor instead.
+func (*PasswordRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *PasswordRequest) GetPassword() string {
+ if x != nil {
+ return x.Password
+ }
+ return ""
+}
+
+type PinRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Pin string `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"`
+}
+
+func (x *PinRequest) Reset() {
+ *x = PinRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PinRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PinRequest) ProtoMessage() {}
+
+func (x *PinRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PinRequest.ProtoReflect.Descriptor instead.
+func (*PinRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *PinRequest) GetPin() string {
+ if x != nil {
+ return x.Pin
+ }
+ return ""
+}
+
+type AuthenticateResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
+ SessionToken string `protobuf:"bytes,2,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"`
+}
+
+func (x *AuthenticateResponse) Reset() {
+ *x = AuthenticateResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AuthenticateResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AuthenticateResponse) ProtoMessage() {}
+
+func (x *AuthenticateResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AuthenticateResponse.ProtoReflect.Descriptor instead.
+func (*AuthenticateResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *AuthenticateResponse) GetSuccess() bool {
+ if x != nil {
+ return x.Success
+ }
+ return false
+}
+
+func (x *AuthenticateResponse) GetSessionToken() string {
+ if x != nil {
+ return x.SessionToken
+ }
+ return ""
+}
+
+// SendStatusUpdateRequest is sent by the proxy to update its status
+type SendStatusUpdateRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ServiceId string `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
+ AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ Status ProxyStatus `protobuf:"varint,3,opt,name=status,proto3,enum=management.ProxyStatus" json:"status,omitempty"`
+ CertificateIssued bool `protobuf:"varint,4,opt,name=certificate_issued,json=certificateIssued,proto3" json:"certificate_issued,omitempty"`
+ ErrorMessage *string `protobuf:"bytes,5,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"`
+}
+
+func (x *SendStatusUpdateRequest) Reset() {
+ *x = SendStatusUpdateRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SendStatusUpdateRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendStatusUpdateRequest) ProtoMessage() {}
+
+func (x *SendStatusUpdateRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SendStatusUpdateRequest.ProtoReflect.Descriptor instead.
+func (*SendStatusUpdateRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *SendStatusUpdateRequest) GetServiceId() string {
+ if x != nil {
+ return x.ServiceId
+ }
+ return ""
+}
+
+func (x *SendStatusUpdateRequest) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (x *SendStatusUpdateRequest) GetStatus() ProxyStatus {
+ if x != nil {
+ return x.Status
+ }
+ return ProxyStatus_PROXY_STATUS_PENDING
+}
+
+func (x *SendStatusUpdateRequest) GetCertificateIssued() bool {
+ if x != nil {
+ return x.CertificateIssued
+ }
+ return false
+}
+
+func (x *SendStatusUpdateRequest) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
+// SendStatusUpdateResponse is intentionally empty to allow for future expansion
+type SendStatusUpdateResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *SendStatusUpdateResponse) Reset() {
+ *x = SendStatusUpdateResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SendStatusUpdateResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendStatusUpdateResponse) ProtoMessage() {}
+
+func (x *SendStatusUpdateResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[13]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SendStatusUpdateResponse.ProtoReflect.Descriptor instead.
+func (*SendStatusUpdateResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{13}
+}
+
+// CreateProxyPeerRequest is sent by the proxy to create a peer connection
+// The token is a one-time authentication token sent via ProxyMapping
+type CreateProxyPeerRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ServiceId string `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
+ AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
+ WireguardPublicKey string `protobuf:"bytes,4,opt,name=wireguard_public_key,json=wireguardPublicKey,proto3" json:"wireguard_public_key,omitempty"`
+ Cluster string `protobuf:"bytes,5,opt,name=cluster,proto3" json:"cluster,omitempty"`
+}
+
+func (x *CreateProxyPeerRequest) Reset() {
+ *x = CreateProxyPeerRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CreateProxyPeerRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateProxyPeerRequest) ProtoMessage() {}
+
+func (x *CreateProxyPeerRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[14]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateProxyPeerRequest.ProtoReflect.Descriptor instead.
+func (*CreateProxyPeerRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *CreateProxyPeerRequest) GetServiceId() string {
+ if x != nil {
+ return x.ServiceId
+ }
+ return ""
+}
+
+func (x *CreateProxyPeerRequest) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (x *CreateProxyPeerRequest) GetToken() string {
+ if x != nil {
+ return x.Token
+ }
+ return ""
+}
+
+func (x *CreateProxyPeerRequest) GetWireguardPublicKey() string {
+ if x != nil {
+ return x.WireguardPublicKey
+ }
+ return ""
+}
+
+func (x *CreateProxyPeerRequest) GetCluster() string {
+ if x != nil {
+ return x.Cluster
+ }
+ return ""
+}
+
+// CreateProxyPeerResponse contains the result of peer creation
+type CreateProxyPeerResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
+ ErrorMessage *string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"`
+}
+
+func (x *CreateProxyPeerResponse) Reset() {
+ *x = CreateProxyPeerResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CreateProxyPeerResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateProxyPeerResponse) ProtoMessage() {}
+
+func (x *CreateProxyPeerResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateProxyPeerResponse.ProtoReflect.Descriptor instead.
+func (*CreateProxyPeerResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *CreateProxyPeerResponse) GetSuccess() bool {
+ if x != nil {
+ return x.Success
+ }
+ return false
+}
+
+func (x *CreateProxyPeerResponse) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
+type GetOIDCURLRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ RedirectUrl string `protobuf:"bytes,3,opt,name=redirect_url,json=redirectUrl,proto3" json:"redirect_url,omitempty"`
+}
+
+func (x *GetOIDCURLRequest) Reset() {
+ *x = GetOIDCURLRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetOIDCURLRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetOIDCURLRequest) ProtoMessage() {}
+
+func (x *GetOIDCURLRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetOIDCURLRequest.ProtoReflect.Descriptor instead.
+func (*GetOIDCURLRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *GetOIDCURLRequest) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *GetOIDCURLRequest) GetAccountId() string {
+ if x != nil {
+ return x.AccountId
+ }
+ return ""
+}
+
+func (x *GetOIDCURLRequest) GetRedirectUrl() string {
+ if x != nil {
+ return x.RedirectUrl
+ }
+ return ""
+}
+
+type GetOIDCURLResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+}
+
+func (x *GetOIDCURLResponse) Reset() {
+ *x = GetOIDCURLResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[17]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetOIDCURLResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetOIDCURLResponse) ProtoMessage() {}
+
+func (x *GetOIDCURLResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[17]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetOIDCURLResponse.ProtoReflect.Descriptor instead.
+func (*GetOIDCURLResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *GetOIDCURLResponse) GetUrl() string {
+ if x != nil {
+ return x.Url
+ }
+ return ""
+}
+
+type ValidateSessionRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Domain string `protobuf:"bytes,1,opt,name=domain,proto3" json:"domain,omitempty"`
+ SessionToken string `protobuf:"bytes,2,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"`
+}
+
+func (x *ValidateSessionRequest) Reset() {
+ *x = ValidateSessionRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[18]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ValidateSessionRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ValidateSessionRequest) ProtoMessage() {}
+
+func (x *ValidateSessionRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[18]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ValidateSessionRequest.ProtoReflect.Descriptor instead.
+func (*ValidateSessionRequest) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *ValidateSessionRequest) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *ValidateSessionRequest) GetSessionToken() string {
+ if x != nil {
+ return x.SessionToken
+ }
+ return ""
+}
+
+type ValidateSessionResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
+ UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
+ UserEmail string `protobuf:"bytes,3,opt,name=user_email,json=userEmail,proto3" json:"user_email,omitempty"`
+ DeniedReason string `protobuf:"bytes,4,opt,name=denied_reason,json=deniedReason,proto3" json:"denied_reason,omitempty"`
+}
+
+func (x *ValidateSessionResponse) Reset() {
+ *x = ValidateSessionResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proxy_service_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ValidateSessionResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ValidateSessionResponse) ProtoMessage() {}
+
+func (x *ValidateSessionResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proxy_service_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ValidateSessionResponse.ProtoReflect.Descriptor instead.
+func (*ValidateSessionResponse) Descriptor() ([]byte, []int) {
+ return file_proxy_service_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *ValidateSessionResponse) GetValid() bool {
+ if x != nil {
+ return x.Valid
+ }
+ return false
+}
+
+func (x *ValidateSessionResponse) GetUserId() string {
+ if x != nil {
+ return x.UserId
+ }
+ return ""
+}
+
+func (x *ValidateSessionResponse) GetUserEmail() string {
+ if x != nil {
+ return x.UserEmail
+ }
+ return ""
+}
+
+func (x *ValidateSessionResponse) GetDeniedReason() string {
+ if x != nil {
+ return x.DeniedReason
+ }
+ return ""
+}
+
+var File_proxy_service_proto protoreflect.FileDescriptor
+
+var file_proxy_service_proto_rawDesc = []byte{
+ 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x22, 0xa3, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
+ 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19,
+ 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61,
+ 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
+ 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18,
+ 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74,
+ 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x15, 0x69, 0x6e, 0x69,
+ 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+ 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x22, 0x39, 0x0a,
+ 0x0b, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04,
+ 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68,
+ 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xaa, 0x01, 0x0a, 0x0e, 0x41, 0x75, 0x74,
+ 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
+ 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x17,
+ 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x67, 0x65, 0x5f,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6d,
+ 0x61, 0x78, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x67, 0x65, 0x53, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12,
+ 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x70, 0x69,
+ 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x04, 0x6f, 0x69, 0x64, 0x63, 0x22, 0xe0, 0x02, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d,
+ 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e,
+ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d,
+ 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a,
+ 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64,
+ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2b, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x04, 0x70, 0x61,
+ 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65,
+ 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74,
+ 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, 0x75, 0x74,
+ 0x68, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x61, 0x73, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x61, 0x73,
+ 0x73, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x72,
+ 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52,
+ 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x22, 0x3f, 0x0a, 0x14, 0x53, 0x65, 0x6e, 0x64,
+ 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x27, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e,
+ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, 0x6e,
+ 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x22, 0xa0, 0x03, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67,
+ 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
+ 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x6f,
+ 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x6f, 0x67, 0x49,
+ 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12,
+ 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68,
+ 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68,
+ 0x6f, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
+ 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64,
+ 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+ 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x49, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61,
+ 0x6e, 0x69, 0x73, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68,
+ 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65,
+ 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x53, 0x75,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x13, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e,
+ 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
+ 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x08,
+ 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x73, 0x73,
+ 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x70,
+ 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x03,
+ 0x70, 0x69, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2d,
+ 0x0a, 0x0f, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x1e, 0x0a,
+ 0x0a, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70,
+ 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x22, 0x55, 0x0a,
+ 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12,
+ 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xf3, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2f,
+ 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78,
+ 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
+ 0x2d, 0x0a, 0x12, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69,
+ 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x65, 0x72,
+ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x28,
+ 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65,
+ 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12,
+ 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+ 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61,
+ 0x72, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x50, 0x75,
+ 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x22, 0x6f, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79,
+ 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07,
+ 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73,
+ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
+ 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01,
+ 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x65, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65, 0x74,
+ 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+ 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72,
+ 0x6c, 0x22, 0x55, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73,
+ 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64,
+ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73,
+ 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8c, 0x01, 0x0a, 0x17, 0x56, 0x61, 0x6c,
+ 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73,
+ 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65,
+ 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69,
+ 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61,
+ 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61,
+ 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x69, 0x65,
+ 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78, 0x79,
+ 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50,
+ 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49,
+ 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54,
+ 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xc8, 0x01,
+ 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a,
+ 0x14, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45,
+ 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x52, 0x4f, 0x58, 0x59,
+ 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01,
+ 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
+ 0x5f, 0x54, 0x55, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41,
+ 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53,
+ 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54,
+ 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f, 0x50,
+ 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54,
+ 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04,
+ 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
+ 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x32, 0xfc, 0x04, 0x0a, 0x0c, 0x50, 0x72, 0x6f,
+ 0x78, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74,
+ 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e,
+ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61,
+ 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
+ 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x65,
+ 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x20, 0x2e, 0x6d, 0x61,
+ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e,
+ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x51, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x12, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75,
+ 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41,
+ 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75,
+ 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78,
+ 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65,
+ 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
+ 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f,
+ 0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b,
+ 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x12, 0x1d, 0x2e, 0x6d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44,
+ 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x61,
+ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43,
+ 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x56,
+ 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69,
+ 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
+ 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_proxy_service_proto_rawDescOnce sync.Once
+ file_proxy_service_proto_rawDescData = file_proxy_service_proto_rawDesc
+)
+
+func file_proxy_service_proto_rawDescGZIP() []byte {
+ file_proxy_service_proto_rawDescOnce.Do(func() {
+ file_proxy_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_service_proto_rawDescData)
+ })
+ return file_proxy_service_proto_rawDescData
+}
+
+var file_proxy_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_proxy_service_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
+var file_proxy_service_proto_goTypes = []interface{}{
+ (ProxyMappingUpdateType)(0), // 0: management.ProxyMappingUpdateType
+ (ProxyStatus)(0), // 1: management.ProxyStatus
+ (*GetMappingUpdateRequest)(nil), // 2: management.GetMappingUpdateRequest
+ (*GetMappingUpdateResponse)(nil), // 3: management.GetMappingUpdateResponse
+ (*PathMapping)(nil), // 4: management.PathMapping
+ (*Authentication)(nil), // 5: management.Authentication
+ (*ProxyMapping)(nil), // 6: management.ProxyMapping
+ (*SendAccessLogRequest)(nil), // 7: management.SendAccessLogRequest
+ (*SendAccessLogResponse)(nil), // 8: management.SendAccessLogResponse
+ (*AccessLog)(nil), // 9: management.AccessLog
+ (*AuthenticateRequest)(nil), // 10: management.AuthenticateRequest
+ (*PasswordRequest)(nil), // 11: management.PasswordRequest
+ (*PinRequest)(nil), // 12: management.PinRequest
+ (*AuthenticateResponse)(nil), // 13: management.AuthenticateResponse
+ (*SendStatusUpdateRequest)(nil), // 14: management.SendStatusUpdateRequest
+ (*SendStatusUpdateResponse)(nil), // 15: management.SendStatusUpdateResponse
+ (*CreateProxyPeerRequest)(nil), // 16: management.CreateProxyPeerRequest
+ (*CreateProxyPeerResponse)(nil), // 17: management.CreateProxyPeerResponse
+ (*GetOIDCURLRequest)(nil), // 18: management.GetOIDCURLRequest
+ (*GetOIDCURLResponse)(nil), // 19: management.GetOIDCURLResponse
+ (*ValidateSessionRequest)(nil), // 20: management.ValidateSessionRequest
+ (*ValidateSessionResponse)(nil), // 21: management.ValidateSessionResponse
+ (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp
+}
+var file_proxy_service_proto_depIdxs = []int32{
+ 22, // 0: management.GetMappingUpdateRequest.started_at:type_name -> google.protobuf.Timestamp
+ 6, // 1: management.GetMappingUpdateResponse.mapping:type_name -> management.ProxyMapping
+ 0, // 2: management.ProxyMapping.type:type_name -> management.ProxyMappingUpdateType
+ 4, // 3: management.ProxyMapping.path:type_name -> management.PathMapping
+ 5, // 4: management.ProxyMapping.auth:type_name -> management.Authentication
+ 9, // 5: management.SendAccessLogRequest.log:type_name -> management.AccessLog
+ 22, // 6: management.AccessLog.timestamp:type_name -> google.protobuf.Timestamp
+ 11, // 7: management.AuthenticateRequest.password:type_name -> management.PasswordRequest
+ 12, // 8: management.AuthenticateRequest.pin:type_name -> management.PinRequest
+ 1, // 9: management.SendStatusUpdateRequest.status:type_name -> management.ProxyStatus
+ 2, // 10: management.ProxyService.GetMappingUpdate:input_type -> management.GetMappingUpdateRequest
+ 7, // 11: management.ProxyService.SendAccessLog:input_type -> management.SendAccessLogRequest
+ 10, // 12: management.ProxyService.Authenticate:input_type -> management.AuthenticateRequest
+ 14, // 13: management.ProxyService.SendStatusUpdate:input_type -> management.SendStatusUpdateRequest
+ 16, // 14: management.ProxyService.CreateProxyPeer:input_type -> management.CreateProxyPeerRequest
+ 18, // 15: management.ProxyService.GetOIDCURL:input_type -> management.GetOIDCURLRequest
+ 20, // 16: management.ProxyService.ValidateSession:input_type -> management.ValidateSessionRequest
+ 3, // 17: management.ProxyService.GetMappingUpdate:output_type -> management.GetMappingUpdateResponse
+ 8, // 18: management.ProxyService.SendAccessLog:output_type -> management.SendAccessLogResponse
+ 13, // 19: management.ProxyService.Authenticate:output_type -> management.AuthenticateResponse
+ 15, // 20: management.ProxyService.SendStatusUpdate:output_type -> management.SendStatusUpdateResponse
+ 17, // 21: management.ProxyService.CreateProxyPeer:output_type -> management.CreateProxyPeerResponse
+ 19, // 22: management.ProxyService.GetOIDCURL:output_type -> management.GetOIDCURLResponse
+ 21, // 23: management.ProxyService.ValidateSession:output_type -> management.ValidateSessionResponse
+ 17, // [17:24] is the sub-list for method output_type
+ 10, // [10:17] is the sub-list for method input_type
+ 10, // [10:10] is the sub-list for extension type_name
+ 10, // [10:10] is the sub-list for extension extendee
+ 0, // [0:10] is the sub-list for field type_name
+}
+
+func init() { file_proxy_service_proto_init() }
+func file_proxy_service_proto_init() {
+ if File_proxy_service_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_proxy_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetMappingUpdateRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetMappingUpdateResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PathMapping); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Authentication); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ProxyMapping); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SendAccessLogRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SendAccessLogResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AccessLog); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AuthenticateRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PasswordRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PinRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AuthenticateResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SendStatusUpdateRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SendStatusUpdateResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CreateProxyPeerRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CreateProxyPeerResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetOIDCURLRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetOIDCURLResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ValidateSessionRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proxy_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ValidateSessionResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_proxy_service_proto_msgTypes[8].OneofWrappers = []interface{}{
+ (*AuthenticateRequest_Password)(nil),
+ (*AuthenticateRequest_Pin)(nil),
+ }
+ file_proxy_service_proto_msgTypes[12].OneofWrappers = []interface{}{}
+ file_proxy_service_proto_msgTypes[15].OneofWrappers = []interface{}{}
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_proxy_service_proto_rawDesc,
+ NumEnums: 2,
+ NumMessages: 20,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_proxy_service_proto_goTypes,
+ DependencyIndexes: file_proxy_service_proto_depIdxs,
+ EnumInfos: file_proxy_service_proto_enumTypes,
+ MessageInfos: file_proxy_service_proto_msgTypes,
+ }.Build()
+ File_proxy_service_proto = out.File
+ file_proxy_service_proto_rawDesc = nil
+ file_proxy_service_proto_goTypes = nil
+ file_proxy_service_proto_depIdxs = nil
+}
diff --git a/shared/management/proto/proxy_service.proto b/shared/management/proto/proxy_service.proto
new file mode 100644
index 000000000..b4e62a52a
--- /dev/null
+++ b/shared/management/proto/proxy_service.proto
@@ -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;
+}
diff --git a/shared/management/proto/proxy_service_grpc.pb.go b/shared/management/proto/proxy_service_grpc.pb.go
new file mode 100644
index 000000000..627b217d8
--- /dev/null
+++ b/shared/management/proto/proxy_service_grpc.pb.go
@@ -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",
+}
diff --git a/shared/management/status/error.go b/shared/management/status/error.go
index ea02173e9..78288aef3 100644
--- a/shared/management/status/error.go
+++ b/shared/management/status/error.go
@@ -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)
+}
diff --git a/util/log.go b/util/log.go
index a951eab87..03547024a 100644
--- a/util/log.go
+++ b/util/log.go
@@ -30,9 +30,14 @@ var (
// InitLog parses and sets log-level input
func InitLog(logLevel string, logs ...string) error {
+ return InitLogger(log.StandardLogger(), logLevel, logs...)
+}
+
+// InitLogger parses and sets log-level input for a logrus logger
+func InitLogger(logger *log.Logger, logLevel string, logs ...string) error {
level, err := log.ParseLevel(logLevel)
if err != nil {
- log.Errorf("Failed parsing log-level %s: %s", logLevel, err)
+ logger.Errorf("Failed parsing log-level %s: %s", logLevel, err)
return err
}
var writers []io.Writer
@@ -41,34 +46,34 @@ func InitLog(logLevel string, logs ...string) error {
for _, logPath := range logs {
switch logPath {
case LogSyslog:
- AddSyslogHook()
+ AddSyslogHookToLogger(logger)
logFmt = "syslog"
case LogConsole:
writers = append(writers, os.Stderr)
case "":
- log.Warnf("empty log path received: %#v", logPath)
+ logger.Warnf("empty log path received: %#v", logPath)
default:
writers = append(writers, newRotatedOutput(logPath))
}
}
if len(writers) > 1 {
- log.SetOutput(io.MultiWriter(writers...))
+ logger.SetOutput(io.MultiWriter(writers...))
} else if len(writers) == 1 {
- log.SetOutput(writers[0])
+ logger.SetOutput(writers[0])
}
switch logFmt {
case "json":
- formatter.SetJSONFormatter(log.StandardLogger())
+ formatter.SetJSONFormatter(logger)
case "syslog":
- formatter.SetSyslogFormatter(log.StandardLogger())
+ formatter.SetSyslogFormatter(logger)
default:
- formatter.SetTextFormatter(log.StandardLogger())
+ formatter.SetTextFormatter(logger)
}
- log.SetLevel(level)
+ logger.SetLevel(level)
- setGRPCLibLogger()
+ setGRPCLibLogger(logger)
return nil
}
@@ -96,8 +101,8 @@ func newRotatedOutput(logPath string) io.Writer {
return lumberjackLogger
}
-func setGRPCLibLogger() {
- logOut := log.StandardLogger().Writer()
+func setGRPCLibLogger(logger *log.Logger) {
+ logOut := logger.Writer()
if os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") != "info" {
grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, logOut, logOut))
return
diff --git a/util/syslog_nonwindows.go b/util/syslog_nonwindows.go
index 328bb8b1c..4a33f21b1 100644
--- a/util/syslog_nonwindows.go
+++ b/util/syslog_nonwindows.go
@@ -10,10 +10,14 @@ import (
)
func AddSyslogHook() {
+ AddSyslogHookToLogger(log.StandardLogger())
+}
+
+func AddSyslogHookToLogger(logger *log.Logger) {
hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
if err != nil {
- log.Errorf("Failed creating syslog hook: %s", err)
+ logger.Errorf("Failed creating syslog hook: %s", err)
}
- log.AddHook(hook)
+ logger.AddHook(hook)
}
diff --git a/util/syslog_windows.go b/util/syslog_windows.go
index 171c1a459..68fddfc5e 100644
--- a/util/syslog_windows.go
+++ b/util/syslog_windows.go
@@ -1,6 +1,13 @@
package util
+import log "github.com/sirupsen/logrus"
+
func AddSyslogHook() {
// The syslog package is not available for Windows. This adapter is needed
// to handle windows build.
}
+
+func AddSyslogHookToLogger(logger *log.Logger) {
+ // The syslog package is not available for Windows. This adapter is needed
+ // to handle windows build.
+}