feat: add support for ssh acl policies

This commit is contained in:
Johan Siebens
2022-10-06 20:49:05 +02:00
parent c70a4cfe6a
commit ddc65d2df9
24 changed files with 1627 additions and 209 deletions
+84
View File
@@ -37,6 +37,8 @@ func tailnetCommand() *coral.Command {
command.AddCommand(disableServiceCollectionCommand())
command.AddCommand(enableFileSharingCommand())
command.AddCommand(disableFileSharingCommand())
command.AddCommand(enableSSHCommand())
command.AddCommand(disableSSHCommand())
command.AddCommand(getDERPMap())
command.AddCommand(setDERPMap())
command.AddCommand(resetDERPMap())
@@ -524,3 +526,85 @@ func disableServiceCollectionCommand() *coral.Command {
return command
}
func enableSSHCommand() *coral.Command {
command := &coral.Command{
Use: "enable-ssh",
Short: "Enable ssh access using tailnet and ACLs.",
SilenceUsage: true,
}
var tailnetID uint64
var tailnetName string
var target = Target{}
target.prepareCommand(command)
command.Flags().StringVar(&tailnetName, "tailnet", "", "Tailnet name. Mutually exclusive with --tailnet-id.")
command.Flags().Uint64Var(&tailnetID, "tailnet-id", 0, "Tailnet ID. Mutually exclusive with --tailnet.")
command.PreRunE = checkRequiredTailnetAndTailnetIdFlags
command.RunE = func(command *coral.Command, args []string) error {
client, err := target.createGRPCClient()
if err != nil {
return err
}
tailnet, err := findTailnet(client, tailnetName, tailnetID)
if err != nil {
return err
}
req := api.EnableSSHRequest{
TailnetId: tailnet.Id,
}
if _, err := client.EnabledSSH(context.Background(), connect.NewRequest(&req)); err != nil {
return err
}
return nil
}
return command
}
func disableSSHCommand() *coral.Command {
command := &coral.Command{
Use: "disable-ssh",
Short: "Disable ssh access using tailnet and ACLs.",
SilenceUsage: true,
}
var tailnetID uint64
var tailnetName string
var target = Target{}
target.prepareCommand(command)
command.Flags().StringVar(&tailnetName, "tailnet", "", "Tailnet name. Mutually exclusive with --tailnet-id.")
command.Flags().Uint64Var(&tailnetID, "tailnet-id", 0, "Tailnet ID. Mutually exclusive with --tailnet.")
command.PreRunE = checkRequiredTailnetAndTailnetIdFlags
command.RunE = func(command *coral.Command, args []string) error {
client, err := target.createGRPCClient()
if err != nil {
return err
}
tailnet, err := findTailnet(client, tailnetName, tailnetID)
if err != nil {
return err
}
req := api.DisableSSHRequest{
TailnetId: tailnet.Id,
}
if _, err := client.DisableSSH(context.Background(), connect.NewRequest(&req)); err != nil {
return err
}
return nil
}
return command
}
@@ -0,0 +1,34 @@
package migration
import (
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
"time"
)
func m202210080700_ssh_action_request() *gormigrate.Migration {
return &gormigrate.Migration{
ID: "202210080700",
Migrate: func(db *gorm.DB) error {
type Tailnet struct {
Name string `gorm:"uniqueIndex"`
Alias *string `gorm:"uniqueIndex"`
SSHEnabled bool
}
type SSHActionRequest struct {
Key string `gorm:"primary_key"`
Action string
SrcMachineID uint64
DstMachineID uint64
CreatedAt time.Time
}
return db.AutoMigrate(
&Tailnet{},
&SSHActionRequest{},
)
},
Rollback: nil,
}
}
@@ -12,6 +12,7 @@ func Migrations() []*gormigrate.Migration {
m202229251530_add_alias_column_constraint(),
m202210040828_add_derpmap_colum(),
m202210070814_add_filesharing_and_servicecollection_columns(),
m202210080700_ssh_action_request(),
}
return migrations
}
+38 -2
View File
@@ -31,6 +31,7 @@ type ACLPolicy struct {
ACLs []ACL `json:"acls"`
TagOwners map[string][]string `json:"tagowners"`
AutoApprovers AutoApprovers `json:"autoApprovers"`
SSHRules []SSHRule `json:"ssh"`
}
type ACL struct {
@@ -39,6 +40,13 @@ type ACL struct {
Dst []string `json:"dst"`
}
type SSHRule struct {
Action string `json:"action"`
Src []string `json:"src"`
Dst []string `json:"dst"`
Users []string `json:"users"`
}
func DefaultPolicy() ACLPolicy {
return ACLPolicy{
ACLs: []ACL{
@@ -116,17 +124,26 @@ func (a ACLPolicy) FindAutoApprovedIPs(routableIPs []netip.Prefix, tags []string
return result
}
func (a ACLPolicy) IsTagOwner(tags []string, p *User) bool {
for _, t := range tags {
if a.isTagOwner(t, p) {
return true
}
}
return false
}
func (a ACLPolicy) CheckTagOwners(tags []string, p *User) error {
var result *multierror.Error
for _, t := range tags {
if ok := a.IsTagOwner(t, p); !ok {
if ok := a.isTagOwner(t, p); !ok {
result = multierror.Append(result, fmt.Errorf("tag [%s] is invalid or not permitted", t))
}
}
return result.ErrorOrNil()
}
func (a ACLPolicy) IsTagOwner(tag string, p *User) bool {
func (a ACLPolicy) isTagOwner(tag string, p *User) bool {
if p.UserType == UserTypeService {
return true
}
@@ -387,6 +404,25 @@ func (a ACLPolicy) expandValuePortToPortRange(s string) ([]tailcfg.PortRange, er
return ports, nil
}
func (a ACLPolicy) isGroupMember(group string, m *Machine) bool {
if m.HasTags() {
return false
}
users, ok := a.Groups[group]
if !ok {
return false
}
for _, u := range users {
if m.HasUser(u) {
return true
}
}
return false
}
func (i *ACLPolicy) Scan(destination interface{}) error {
switch value := destination.(type) {
case []byte:
+150
View File
@@ -0,0 +1,150 @@
package domain
import (
"strings"
"tailscale.com/tailcfg"
)
func (a ACLPolicy) BuildSSHPolicy(srcs []Machine, dst *Machine) *tailcfg.SSHPolicy {
var rules []*tailcfg.SSHRule
expandSrcAliases := func(aliases []string, u *User) []*tailcfg.SSHPrincipal {
var allSrcIPsSet = &StringSet{}
for _, alias := range aliases {
for _, src := range srcs {
srcIPs := a.expandSSHSrcAlias(&src, alias, u)
allSrcIPsSet.Add(srcIPs...)
}
}
var result = []*tailcfg.SSHPrincipal{}
for _, i := range allSrcIPsSet.Items() {
result = append(result, &tailcfg.SSHPrincipal{NodeIP: i})
}
return result
}
for _, rule := range a.SSHRules {
if rule.Action != "accept" && rule.Action != "check" {
continue
}
var action = &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
}
if rule.Action == "check" {
action = &tailcfg.SSHAction{
HoldAndDelegate: "https://unused/machine/ssh/action/$SRC_NODE_ID/to/$DST_NODE_ID",
}
}
selfUsers, otherUsers := a.expandSSHDstToSSHUsers(dst, rule)
if len(selfUsers) != 0 {
principals := expandSrcAliases(rule.Src, &dst.User)
if len(principals) != 0 {
rules = append(rules, &tailcfg.SSHRule{
Principals: principals,
SSHUsers: selfUsers,
Action: action,
})
}
}
if len(otherUsers) != 0 {
principals := expandSrcAliases(rule.Src, nil)
if len(principals) != 0 {
rules = append(rules, &tailcfg.SSHRule{
Principals: principals,
SSHUsers: otherUsers,
Action: action,
})
}
}
}
return &tailcfg.SSHPolicy{Rules: rules}
}
func (a ACLPolicy) expandSSHSrcAlias(m *Machine, alias string, dstUser *User) []string {
if dstUser != nil {
if !m.HasUser(dstUser.Name) || m.HasTags() {
return []string{}
}
if alias == AutoGroupMembers {
return m.IPs()
}
if strings.Contains(alias, "@") && m.HasUser(alias) {
return m.IPs()
}
if strings.HasPrefix(alias, "group:") && a.isGroupMember(alias, m) {
return m.IPs()
}
return []string{}
}
if alias == AutoGroupMembers && !m.HasTags() {
return m.IPs()
}
if strings.Contains(alias, "@") && !m.HasTags() && m.HasUser(alias) {
return m.IPs()
}
if strings.HasPrefix(alias, "group:") && !m.HasTags() && a.isGroupMember(alias, m) {
return m.IPs()
}
if strings.HasPrefix(alias, "tag:") && m.HasTag(alias) {
return m.IPs()
}
return []string{}
}
func (a ACLPolicy) expandSSHDstToSSHUsers(m *Machine, rule SSHRule) (map[string]string, map[string]string) {
users := buildSSHUsers(rule.Users)
var selfUsers map[string]string
var otherUsers map[string]string
for _, d := range rule.Dst {
if strings.HasPrefix(d, "tag:") && m.HasTag(d) {
otherUsers = users
}
if m.HasUser(d) || d == AutoGroupSelf {
selfUsers = users
}
}
return selfUsers, otherUsers
}
func buildSSHUsers(users []string) map[string]string {
var autogroupNonRoot = false
m := make(map[string]string)
for _, u := range users {
if u == "autogroup:nonroot" {
m["*"] = "="
autogroupNonRoot = true
} else {
m[u] = u
}
}
// disable root when autogroup:nonroot is used and root is not explicitly enabled
if _, exists := m["root"]; !exists && autogroupNonRoot {
m["root"] = ""
}
return m
}
+364
View File
@@ -0,0 +1,364 @@
package domain
import (
"encoding/json"
"fmt"
"github.com/stretchr/testify/assert"
"tailscale.com/tailcfg"
"testing"
)
func TestACLPolicy_BuildSSHPolicy_(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"autogroup:members"},
Dst: []string{"autogroup:self"},
Users: []string{"autogroup:nonroot"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: []*tailcfg.SSHPrincipal{
{NodeIP: p1.IPv4.String()},
{NodeIP: p1.IPv6.String()},
},
SSHUsers: map[string]string{
"*": "=",
"root": "",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithGroup(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
Groups: map[string][]string{
"group:sre": {
"john@example.com",
},
},
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"group:sre"},
Dst: []string{"tag:web"},
Users: []string{"autogroup:nonroot", "root"},
},
},
}
dst := createMachine("john@example.com", "tag:web")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: []*tailcfg.SSHPrincipal{
{NodeIP: p1.IPv4.String()},
{NodeIP: p1.IPv6.String()},
},
SSHUsers: map[string]string{
"*": "=",
"root": "root",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithMatchingUsers(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"john@example.com"},
Dst: []string{"john@example.com"},
Users: []string{"autogroup:nonroot", "root"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: sshPrincipalsFromMachines(*p1),
SSHUsers: map[string]string{
"*": "=",
"root": "root",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithMatchingUsersInGroup(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
Groups: map[string][]string{
"group:sre": {"jane@example.com", "john@example.com"},
},
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"group:sre"},
Dst: []string{"john@example.com"},
Users: []string{"autogroup:nonroot", "root"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: sshPrincipalsFromMachines(*p1),
SSHUsers: map[string]string{
"*": "=",
"root": "root",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithNoMatchingUsers(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"jane@example.com"},
Dst: []string{"john@example.com"},
Users: []string{"autogroup:nonroot", "root"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
assert.Nil(t, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithTags(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("nick@example.com")
p3 := createMachine("nick@example.com", "tag:web")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"john@example.com", "tag:web"},
Dst: []string{"tag:web"},
Users: []string{"ubuntu"},
},
},
}
dst := createMachine("john@example.com", "tag:web")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2, *p3}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: sshPrincipalsFromMachines(*p1, *p3),
SSHUsers: map[string]string{
"ubuntu": "ubuntu",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithTagsInDstAndAutogroupMemberInSrc(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("nick@example.com")
p3 := createMachine("nick@example.com", "tag:web")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"autogroup:members"},
Dst: []string{"tag:web"},
Users: []string{"ubuntu"},
},
},
}
dst := createMachine("john@example.com", "tag:web")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2, *p3}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: sshPrincipalsFromMachines(*p1, *p2),
SSHUsers: map[string]string{
"ubuntu": "ubuntu",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithUserInDstAndNonMatchingSrc(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"jane@example.com"},
Dst: []string{"john@example.com"},
Users: []string{"autogroup:nonroot"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
assert.Nil(t, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithUserInDstAndAutogroupMembersSrc(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"autogroup:members"},
Dst: []string{"john@example.com"},
Users: []string{"autogroup:nonroot"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
expectedRules := []*tailcfg.SSHRule{
{
Principals: sshPrincipalsFromMachines(*p1),
SSHUsers: map[string]string{
"*": "=",
"root": "",
},
Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
},
}
assert.Equal(t, expectedRules, actualRules.Rules)
}
func TestACLPolicy_BuildSSHPolicy_WithAutogroupSelfAndTagSrc(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com", "tag:web")
policy := ACLPolicy{
SSHRules: []SSHRule{
{
Action: "accept",
Src: []string{"tag:web"},
Dst: []string{"autogroup:self"},
Users: []string{"autogroup:nonroot"},
},
},
}
dst := createMachine("john@example.com")
actualRules := policy.BuildSSHPolicy([]Machine{*p1, *p2}, dst)
assert.Nil(t, actualRules.Rules)
}
func printRules(rules []*tailcfg.SSHRule) {
indent, err := json.MarshalIndent(rules, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(indent))
}
func sshPrincipalsFromMachines(machines ...Machine) []*tailcfg.SSHPrincipal {
x := StringSet{}
for _, m := range machines {
x.Add(m.IPv4.String(), m.IPv6.String())
}
var result = []*tailcfg.SSHPrincipal{}
for _, i := range x.Items() {
result = append(result, &tailcfg.SSHPrincipal{NodeIP: i})
}
return result
}
-10
View File
@@ -1,8 +1,6 @@
package domain
import (
"encoding/json"
"fmt"
"github.com/jsiebens/ionscale/internal/addr"
"github.com/stretchr/testify/assert"
"net/netip"
@@ -11,14 +9,6 @@ import (
"testing"
)
func printRules(rules []tailcfg.FilterRule) {
indent, err := json.MarshalIndent(rules, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(indent))
}
func TestACLPolicy_BuildFilterRulesWildcards(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
+4
View File
@@ -78,6 +78,10 @@ type Repository interface {
GetAuthenticationRequest(ctx context.Context, key string) (*AuthenticationRequest, error)
DeleteAuthenticationRequest(ctx context.Context, key string) error
SaveSSHActionRequest(ctx context.Context, session *SSHActionRequest) error
GetSSHActionRequest(ctx context.Context, key string) (*SSHActionRequest, error)
DeleteSSHActionRequest(ctx context.Context, key string) error
Transaction(func(rp Repository) error) error
}
+46
View File
@@ -0,0 +1,46 @@
package domain
import (
"context"
"errors"
"gorm.io/gorm"
"time"
)
type SSHActionRequest struct {
Key string `gorm:"primary_key"`
Action string
SrcMachineID uint64
DstMachineID uint64
CreatedAt time.Time
}
func (r *repository) SaveSSHActionRequest(ctx context.Context, session *SSHActionRequest) error {
tx := r.withContext(ctx).Save(session)
if tx.Error != nil {
return tx.Error
}
return nil
}
func (r *repository) GetSSHActionRequest(ctx context.Context, key string) (*SSHActionRequest, error) {
var m SSHActionRequest
tx := r.withContext(ctx).First(&m, "key = ?", key)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
if tx.Error != nil {
return nil, tx.Error
}
return &m, nil
}
func (r *repository) DeleteSSHActionRequest(ctx context.Context, key string) error {
tx := r.withContext(ctx).Delete(&SSHActionRequest{Key: key})
return tx.Error
}
+1
View File
@@ -20,6 +20,7 @@ type Tailnet struct {
DERPMap DERPMap
ServiceCollectionEnabled bool
FileSharingEnabled bool
SSHEnabled bool
}
func (t Tailnet) GetDERPMap(ctx context.Context, fallack DefaultDERPMap) (*DERPMap, error) {
+50 -3
View File
@@ -58,17 +58,26 @@ type oauthState struct {
func (h *AuthenticationHandlers) StartCliAuth(c echo.Context) error {
ctx := c.Request().Context()
flow := c.Param("flow")
key := c.Param("key")
if flow == "c" {
if s, err := h.repository.GetAuthenticationRequest(ctx, key); err != nil || s == nil {
return c.Redirect(http.StatusFound, "/a/error")
}
}
if flow == "s" {
if s, err := h.repository.GetSSHActionRequest(ctx, key); err != nil || s == nil {
return c.Redirect(http.StatusFound, "/a/error")
}
}
if h.authProvider == nil {
return c.Redirect(http.StatusFound, "/a/error")
}
state, err := h.createState("c", key)
state, err := h.createState(flow, key)
if err != nil {
return err
}
@@ -134,12 +143,48 @@ func (h *AuthenticationHandlers) Callback(c echo.Context) error {
return err
}
tailnets, err := h.listAvailableTailnets(ctx, user)
account, _, err := h.repository.GetOrCreateAccount(ctx, user.ID, user.Name)
if err != nil {
return err
}
account, _, err := h.repository.GetOrCreateAccount(ctx, user.ID, user.Name)
if state.Flow == "s" {
sshActionReq, err := h.repository.GetSSHActionRequest(ctx, state.Key)
if err != nil || sshActionReq == nil {
return c.Redirect(http.StatusFound, "/a/error?e=ua")
}
machine, err := h.repository.GetMachine(ctx, sshActionReq.SrcMachineID)
if err != nil || sshActionReq == nil {
return c.Redirect(http.StatusFound, "/a/error")
}
policy := machine.Tailnet.ACLPolicy
if machine.HasTags() && policy.IsTagOwner(machine.Tags, &domain.User{Name: account.LoginName, UserType: domain.UserTypePerson}) {
sshActionReq.Action = "accept"
if err := h.repository.SaveSSHActionRequest(ctx, sshActionReq); err != nil {
return c.Redirect(http.StatusFound, "/a/error")
}
return c.Redirect(http.StatusFound, "/a/success")
}
if machine.User.AccountID != nil && *machine.User.AccountID == account.ID {
sshActionReq.Action = "accept"
if err := h.repository.SaveSSHActionRequest(ctx, sshActionReq); err != nil {
return c.Redirect(http.StatusFound, "/a/error")
}
return c.Redirect(http.StatusFound, "/a/success")
}
sshActionReq.Action = "reject"
if err := h.repository.SaveSSHActionRequest(ctx, sshActionReq); err != nil {
return c.Redirect(http.StatusFound, "/a/error")
}
return c.Redirect(http.StatusFound, "/a/error?e=nmo")
}
tailnets, err := h.listAvailableTailnets(ctx, user)
if err != nil {
return err
}
@@ -248,6 +293,8 @@ func (h *AuthenticationHandlers) Error(c echo.Context) error {
return c.Render(http.StatusForbidden, "unauthorized.html", nil)
case "nto":
return c.Render(http.StatusForbidden, "notagowner.html", nil)
case "nmo":
return c.Render(http.StatusForbidden, "notmachineowner.html", nil)
}
return c.Render(http.StatusOK, "error.html", nil)
}
+8 -3
View File
@@ -226,6 +226,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
return nil, nil, "", err
}
hostinfo := tailcfg.Hostinfo(m.HostInfo)
node, user, err := mapping.ToNode(m, tailnet, false)
if err != nil {
return nil, nil, "", err
@@ -277,7 +278,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
return nil, nil, "", err
}
rules := policies.BuildFilterRules(candidatePeers, m)
filterRules := policies.BuildFilterRules(candidatePeers, m)
controlTime := time.Now().UTC()
var mapResponse *tailcfg.MapResponse
@@ -287,7 +288,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
KeepAlive: false,
Node: node,
DNSConfig: mapping.ToDNSConfig(m, validPeers, &m.Tailnet, &dnsConfig),
PacketFilter: rules,
PacketFilter: filterRules,
DERPMap: &derpMap.DERPMap,
Domain: domain.SanitizeTailnetName(m.Tailnet.Name),
Peers: changedPeers,
@@ -302,7 +303,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
mapResponse = &tailcfg.MapResponse{
Node: node,
DNSConfig: mapping.ToDNSConfig(m, validPeers, &m.Tailnet, &dnsConfig),
PacketFilter: rules,
PacketFilter: filterRules,
Domain: domain.SanitizeTailnetName(m.Tailnet.Name),
PeersChanged: changedPeers,
PeersRemoved: removedPeers,
@@ -316,6 +317,10 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
}
}
if tailnet.SSHEnabled && hostinfo.TailscaleSSHEnabled() {
mapResponse.SSHPolicy = policies.BuildSSHPolicy(candidatePeers, m)
}
if request.OmitPeers {
mapResponse.PeersChanged = nil
mapResponse.PeersRemoved = nil
+113
View File
@@ -0,0 +1,113 @@
package handlers
import (
"fmt"
"github.com/jsiebens/ionscale/internal/bind"
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/domain"
"github.com/jsiebens/ionscale/internal/util"
"github.com/labstack/echo/v4"
"net/http"
"tailscale.com/tailcfg"
"time"
)
func NewSSHActionHandlers(createBinder bind.Factory, config *config.Config, repository domain.Repository) *SSHActionHandlers {
return &SSHActionHandlers{
createBinder: createBinder,
repository: repository,
config: config,
}
}
type SSHActionHandlers struct {
createBinder bind.Factory
repository domain.Repository
config *config.Config
}
type sshActionRequestData struct {
SrcMachineID uint64 `param:"src_machine_id"`
DstMachineID uint64 `param:"dst_machine_id"`
}
func (h *SSHActionHandlers) StartAuth(c echo.Context) error {
ctx := c.Request().Context()
binder, err := h.createBinder(c)
if err != nil {
return err
}
data := new(sshActionRequestData)
if err = c.Bind(data); err != nil {
return c.String(http.StatusBadRequest, "bad request")
}
key := util.RandStringBytes(8)
request := &domain.SSHActionRequest{
Key: key,
SrcMachineID: data.SrcMachineID,
DstMachineID: data.DstMachineID,
CreatedAt: time.Now().UTC(),
}
authUrl := h.config.CreateUrl("/a/s/%s", key)
if err := h.repository.SaveSSHActionRequest(ctx, request); err != nil {
return err
}
resp := &tailcfg.SSHAction{
Message: fmt.Sprintf("# Tailscale SSH requires an additional check.\n# To authenticate, visit: %s\n", authUrl),
HoldAndDelegate: fmt.Sprintf("https://unused/machine/ssh/action/check/%s", key),
}
return binder.WriteResponse(c, http.StatusOK, resp)
}
func (h *SSHActionHandlers) CheckAuth(c echo.Context) error {
// Listen to connection close
ctx := c.Request().Context()
notify := ctx.Done()
binder, err := h.createBinder(c)
if err != nil {
return err
}
tick := time.NewTicker(2 * time.Second)
defer func() { tick.Stop() }()
key := c.Param("key")
for {
select {
case <-tick.C:
m, err := h.repository.GetSSHActionRequest(ctx, key)
if err != nil || m == nil {
return binder.WriteResponse(c, http.StatusOK, &tailcfg.SSHAction{Reject: true})
}
if m.Action == "accept" {
action := &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
}
_ = h.repository.DeleteSSHActionRequest(ctx, key)
return binder.WriteResponse(c, http.StatusOK, action)
}
if m.Action == "reject" {
action := &tailcfg.SSHAction{Reject: true}
_ = h.repository.DeleteSSHActionRequest(ctx, key)
return binder.WriteResponse(c, http.StatusOK, action)
}
case <-notify:
return nil
}
}
}
+4
View File
@@ -121,6 +121,10 @@ func ToNode(m *domain.Machine, tailnet *domain.Tailnet, peer bool) (*tailcfg.Nod
if tailnet.FileSharingEnabled {
capabilities = append(capabilities, tailcfg.CapabilityFileSharing)
}
if tailnet.SSHEnabled {
capabilities = append(capabilities, tailcfg.CapabilitySSH)
}
}
nKey, err := util.ParseNodePublicKey(m.NodeKey)
+4 -1
View File
@@ -97,6 +97,7 @@ func Start(c *config.Config) error {
pollNetMapHandler := handlers.NewPollNetMapHandler(bind.DefaultBinder(p), brokers, repository, offlineTimers)
dnsHandlers := handlers.NewDNSHandlers(bind.DefaultBinder(p), dnsProvider)
idTokenHandlers := handlers.NewIDTokenHandlers(bind.DefaultBinder(p), c, repository)
sshActionHandlers := handlers.NewSSHActionHandlers(bind.DefaultBinder(p), c, repository)
e := echo.New()
e.Use(EchoLogger(logger))
@@ -105,6 +106,8 @@ func Start(c *config.Config) error {
e.POST("/machine/map", pollNetMapHandler.PollNetMap)
e.POST("/machine/set-dns", dnsHandlers.SetDNS)
e.POST("/machine/id-token", idTokenHandlers.FetchToken)
e.GET("/machine/ssh/action/:src_machine_id/to/:dst_machine_id", sshActionHandlers.StartAuth)
e.GET("/machine/ssh/action/check/:key", sshActionHandlers.CheckAuth)
return e
}
@@ -161,7 +164,7 @@ func Start(c *config.Config) error {
}))
auth.GET("/:key", authenticationHandlers.StartAuth)
auth.POST("/:key", authenticationHandlers.ProcessAuth)
auth.GET("/c/:key", authenticationHandlers.StartCliAuth)
auth.GET("/:flow/:key", authenticationHandlers.StartCliAuth)
auth.GET("/callback", authenticationHandlers.Callback)
auth.POST("/callback", authenticationHandlers.EndOAuth)
auth.GET("/success", authenticationHandlers.Success)
+52
View File
@@ -334,3 +334,55 @@ func (s *Service) DisableServiceCollection(ctx context.Context, req *connect.Req
return connect.NewResponse(&api.DisableServiceCollectionResponse{}), nil
}
func (s *Service) EnabledSSH(ctx context.Context, req *connect.Request[api.EnableSSHRequest]) (*connect.Response[api.EnableSSHResponse], error) {
principal := CurrentPrincipal(ctx)
if !principal.IsSystemAdmin() && !principal.IsTailnetAdmin(req.Msg.TailnetId) {
return nil, connect.NewError(connect.CodePermissionDenied, errors.New("permission denied"))
}
tailnet, err := s.repository.GetTailnet(ctx, req.Msg.TailnetId)
if err != nil {
return nil, err
}
if tailnet == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("tailnet not found"))
}
if !tailnet.SSHEnabled {
tailnet.SSHEnabled = true
if err := s.repository.SaveTailnet(ctx, tailnet); err != nil {
return nil, err
}
s.pubsub.Publish(tailnet.ID, &broker.Signal{})
}
return connect.NewResponse(&api.EnableSSHResponse{}), nil
}
func (s *Service) DisableSSH(ctx context.Context, req *connect.Request[api.DisableSSHRequest]) (*connect.Response[api.DisableSSHResponse], error) {
principal := CurrentPrincipal(ctx)
if !principal.IsSystemAdmin() && !principal.IsTailnetAdmin(req.Msg.TailnetId) {
return nil, connect.NewError(connect.CodePermissionDenied, errors.New("permission denied"))
}
tailnet, err := s.repository.GetTailnet(ctx, req.Msg.TailnetId)
if err != nil {
return nil, err
}
if tailnet == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.New("tailnet not found"))
}
if tailnet.SSHEnabled {
tailnet.SSHEnabled = false
if err := s.repository.SaveTailnet(ctx, tailnet); err != nil {
return nil, err
}
s.pubsub.Publish(tailnet.ID, &broker.Signal{})
}
return connect.NewResponse(&api.DisableSSHResponse{}), nil
}
+63
View File
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
width: 100%;
height: 100vh;
padding: 10px;
background: #379683;
}
.wrapper {
background: #fff;
max-width: 400px;
width: 100%;
margin: 120px auto;
padding: 25px;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.selectionList li {
position: relative;
list-style: none;
height: 45px;
line-height: 45px;
margin-bottom: 8px;
background: #f2f2f2;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
}
.selectionList li button {
margin: 0;
display: block;
width: 100%;
height: 100%;
border: none;
}
</style>
<title>ionscale</title>
</head>
<body>
<div class="wrapper">
<div style="text-align: center">
<p><b>Authentication successful</b></p>
<small>but you're <b style="color: red">not</b> a valid owner of the machine</small>
</div>
</div>
</body>
</html>
+154 -52
View File
@@ -218,6 +218,7 @@ type ACLPolicy struct {
Acls []*ACL `protobuf:"bytes,3,rep,name=acls,proto3" json:"acls,omitempty"`
Tagowners map[string]*structpb.ListValue `protobuf:"bytes,4,rep,name=tagowners,proto3" json:"tagowners,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Autoapprovers *AutoApprovers `protobuf:"bytes,5,opt,name=autoapprovers,proto3" json:"autoapprovers,omitempty"`
Ssh []*SSHRule `protobuf:"bytes,6,rep,name=ssh,proto3" json:"ssh,omitempty"`
}
func (x *ACLPolicy) Reset() {
@@ -287,6 +288,13 @@ func (x *ACLPolicy) GetAutoapprovers() *AutoApprovers {
return nil
}
func (x *ACLPolicy) GetSsh() []*SSHRule {
if x != nil {
return x.Ssh
}
return nil
}
type ACL struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -405,6 +413,77 @@ func (x *AutoApprovers) GetExitnode() []string {
return nil
}
type SSHRule struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Action string `protobuf:"bytes,1,opt,name=action,proto3" json:"action,omitempty"`
Src []string `protobuf:"bytes,2,rep,name=src,proto3" json:"src,omitempty"`
Dst []string `protobuf:"bytes,3,rep,name=dst,proto3" json:"dst,omitempty"`
Users []string `protobuf:"bytes,4,rep,name=users,proto3" json:"users,omitempty"`
}
func (x *SSHRule) Reset() {
*x = SSHRule{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_acl_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SSHRule) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SSHRule) ProtoMessage() {}
func (x *SSHRule) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_acl_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 SSHRule.ProtoReflect.Descriptor instead.
func (*SSHRule) Descriptor() ([]byte, []int) {
return file_ionscale_v1_acl_proto_rawDescGZIP(), []int{7}
}
func (x *SSHRule) GetAction() string {
if x != nil {
return x.Action
}
return ""
}
func (x *SSHRule) GetSrc() []string {
if x != nil {
return x.Src
}
return nil
}
func (x *SSHRule) GetDst() []string {
if x != nil {
return x.Dst
}
return nil
}
func (x *SSHRule) GetUsers() []string {
if x != nil {
return x.Users
}
return nil
}
var File_ionscale_v1_acl_proto protoreflect.FileDescriptor
var file_ionscale_v1_acl_proto_rawDesc = []byte{
@@ -429,7 +508,7 @@ var file_ionscale_v1_acl_proto_rawDesc = []byte{
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x43, 0x4c, 0x50,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x16, 0x0a,
0x14, 0x53, 0x65, 0x74, 0x41, 0x43, 0x4c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x98, 0x04, 0x0a, 0x09, 0x41, 0x43, 0x4c, 0x50, 0x6f, 0x6c,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc0, 0x04, 0x0a, 0x09, 0x41, 0x43, 0x4c, 0x50, 0x6f, 0x6c,
0x69, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x43, 0x4c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73,
@@ -448,42 +527,51 @@ var file_ionscale_v1_acl_proto_rawDesc = []byte{
0x76, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x41, 0x70, 0x70,
0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x6f, 0x61, 0x70, 0x70, 0x72,
0x6f, 0x76, 0x65, 0x72, 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a,
0x55, 0x0a, 0x0b, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x0e, 0x54, 0x61, 0x67, 0x6f, 0x77, 0x6e,
0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x22, 0x41, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x10, 0x0a, 0x03, 0x73, 0x72, 0x63, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72,
0x63, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03,
0x64, 0x73, 0x74, 0x22, 0xc2, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x6f, 0x41, 0x70, 0x70, 0x72,
0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72,
0x73, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x69, 0x74, 0x6e, 0x6f, 0x64,
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x69, 0x74, 0x6e, 0x6f, 0x64,
0x65, 0x1a, 0x55, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x03, 0x73, 0x73, 0x68, 0x18, 0x06, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x53, 0x48, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x03, 0x73, 0x73, 0x68, 0x1a, 0x38, 0x0a,
0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x55, 0x0a, 0x0b, 0x47, 0x72, 0x6f, 0x75, 0x70,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58,
0x0a, 0x0e, 0x54, 0x61, 0x67, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f,
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x41, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12,
0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72, 0x63, 0x18, 0x02,
0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, 0x74,
0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x74, 0x22, 0xc2, 0x01, 0x0a, 0x0d,
0x41, 0x75, 0x74, 0x6f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x3e, 0x0a,
0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f,
0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a,
0x08, 0x65, 0x78, 0x69, 0x74, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
0x08, 0x65, 0x78, 0x69, 0x74, 0x6e, 0x6f, 0x64, 0x65, 0x1a, 0x55, 0x0a, 0x0b, 0x52, 0x6f, 0x75,
0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x22, 0x5b, 0x0a, 0x07, 0x53, 0x53, 0x48, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72, 0x63, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
0x52, 0x03, 0x73, 0x72, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03,
0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x42, 0x3d, 0x5a,
0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65,
0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b,
0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76,
0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -498,7 +586,7 @@ func file_ionscale_v1_acl_proto_rawDescGZIP() []byte {
return file_ionscale_v1_acl_proto_rawDescData
}
var file_ionscale_v1_acl_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_ionscale_v1_acl_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_ionscale_v1_acl_proto_goTypes = []interface{}{
(*GetACLPolicyRequest)(nil), // 0: ionscale.v1.GetACLPolicyRequest
(*GetACLPolicyResponse)(nil), // 1: ionscale.v1.GetACLPolicyResponse
@@ -507,29 +595,31 @@ var file_ionscale_v1_acl_proto_goTypes = []interface{}{
(*ACLPolicy)(nil), // 4: ionscale.v1.ACLPolicy
(*ACL)(nil), // 5: ionscale.v1.ACL
(*AutoApprovers)(nil), // 6: ionscale.v1.AutoApprovers
nil, // 7: ionscale.v1.ACLPolicy.HostsEntry
nil, // 8: ionscale.v1.ACLPolicy.GroupsEntry
nil, // 9: ionscale.v1.ACLPolicy.TagownersEntry
nil, // 10: ionscale.v1.AutoApprovers.RoutesEntry
(*structpb.ListValue)(nil), // 11: google.protobuf.ListValue
(*SSHRule)(nil), // 7: ionscale.v1.SSHRule
nil, // 8: ionscale.v1.ACLPolicy.HostsEntry
nil, // 9: ionscale.v1.ACLPolicy.GroupsEntry
nil, // 10: ionscale.v1.ACLPolicy.TagownersEntry
nil, // 11: ionscale.v1.AutoApprovers.RoutesEntry
(*structpb.ListValue)(nil), // 12: google.protobuf.ListValue
}
var file_ionscale_v1_acl_proto_depIdxs = []int32{
4, // 0: ionscale.v1.GetACLPolicyResponse.policy:type_name -> ionscale.v1.ACLPolicy
4, // 1: ionscale.v1.SetACLPolicyRequest.policy:type_name -> ionscale.v1.ACLPolicy
7, // 2: ionscale.v1.ACLPolicy.hosts:type_name -> ionscale.v1.ACLPolicy.HostsEntry
8, // 3: ionscale.v1.ACLPolicy.groups:type_name -> ionscale.v1.ACLPolicy.GroupsEntry
8, // 2: ionscale.v1.ACLPolicy.hosts:type_name -> ionscale.v1.ACLPolicy.HostsEntry
9, // 3: ionscale.v1.ACLPolicy.groups:type_name -> ionscale.v1.ACLPolicy.GroupsEntry
5, // 4: ionscale.v1.ACLPolicy.acls:type_name -> ionscale.v1.ACL
9, // 5: ionscale.v1.ACLPolicy.tagowners:type_name -> ionscale.v1.ACLPolicy.TagownersEntry
10, // 5: ionscale.v1.ACLPolicy.tagowners:type_name -> ionscale.v1.ACLPolicy.TagownersEntry
6, // 6: ionscale.v1.ACLPolicy.autoapprovers:type_name -> ionscale.v1.AutoApprovers
10, // 7: ionscale.v1.AutoApprovers.routes:type_name -> ionscale.v1.AutoApprovers.RoutesEntry
11, // 8: ionscale.v1.ACLPolicy.GroupsEntry.value:type_name -> google.protobuf.ListValue
11, // 9: ionscale.v1.ACLPolicy.TagownersEntry.value:type_name -> google.protobuf.ListValue
11, // 10: ionscale.v1.AutoApprovers.RoutesEntry.value:type_name -> google.protobuf.ListValue
11, // [11:11] is the sub-list for method output_type
11, // [11:11] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
7, // 7: ionscale.v1.ACLPolicy.ssh:type_name -> ionscale.v1.SSHRule
11, // 8: ionscale.v1.AutoApprovers.routes:type_name -> ionscale.v1.AutoApprovers.RoutesEntry
12, // 9: ionscale.v1.ACLPolicy.GroupsEntry.value:type_name -> google.protobuf.ListValue
12, // 10: ionscale.v1.ACLPolicy.TagownersEntry.value:type_name -> google.protobuf.ListValue
12, // 11: ionscale.v1.AutoApprovers.RoutesEntry.value:type_name -> google.protobuf.ListValue
12, // [12:12] is the sub-list for method output_type
12, // [12:12] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_ionscale_v1_acl_proto_init() }
@@ -623,6 +713,18 @@ func file_ionscale_v1_acl_proto_init() {
return nil
}
}
file_ionscale_v1_acl_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SSHRule); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -630,7 +732,7 @@ func file_ionscale_v1_acl_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_acl_proto_rawDesc,
NumEnums: 0,
NumMessages: 11,
NumMessages: 12,
NumExtensions: 0,
NumServices: 0,
},
+145 -127
View File
@@ -48,7 +48,7 @@ var file_ionscale_v1_ionscale_proto_rawDesc = []byte{
0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31,
0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x72, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x32, 0xc5, 0x1d, 0x0a, 0x0f, 0x49, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53,
0x74, 0x6f, 0x32, 0xe5, 0x1e, 0x0a, 0x0f, 0x49, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
@@ -145,6 +145,16 @@ var file_ionscale_v1_ionscale_proto_rawDesc = []byte{
0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43,
0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0a, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x53, 0x53,
0x48, 0x12, 0x1d, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1e, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45,
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0a, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48,
0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1f, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x20, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65,
@@ -309,66 +319,70 @@ var file_ionscale_v1_ionscale_proto_goTypes = []interface{}{
(*DisableFileSharingRequest)(nil), // 13: ionscale.v1.DisableFileSharingRequest
(*EnableServiceCollectionRequest)(nil), // 14: ionscale.v1.EnableServiceCollectionRequest
(*DisableServiceCollectionRequest)(nil), // 15: ionscale.v1.DisableServiceCollectionRequest
(*GetDNSConfigRequest)(nil), // 16: ionscale.v1.GetDNSConfigRequest
(*SetDNSConfigRequest)(nil), // 17: ionscale.v1.SetDNSConfigRequest
(*GetIAMPolicyRequest)(nil), // 18: ionscale.v1.GetIAMPolicyRequest
(*SetIAMPolicyRequest)(nil), // 19: ionscale.v1.SetIAMPolicyRequest
(*GetACLPolicyRequest)(nil), // 20: ionscale.v1.GetACLPolicyRequest
(*SetACLPolicyRequest)(nil), // 21: ionscale.v1.SetACLPolicyRequest
(*GetAuthKeyRequest)(nil), // 22: ionscale.v1.GetAuthKeyRequest
(*CreateAuthKeyRequest)(nil), // 23: ionscale.v1.CreateAuthKeyRequest
(*DeleteAuthKeyRequest)(nil), // 24: ionscale.v1.DeleteAuthKeyRequest
(*ListAuthKeysRequest)(nil), // 25: ionscale.v1.ListAuthKeysRequest
(*ListUsersRequest)(nil), // 26: ionscale.v1.ListUsersRequest
(*DeleteUserRequest)(nil), // 27: ionscale.v1.DeleteUserRequest
(*GetMachineRequest)(nil), // 28: ionscale.v1.GetMachineRequest
(*ListMachinesRequest)(nil), // 29: ionscale.v1.ListMachinesRequest
(*ExpireMachineRequest)(nil), // 30: ionscale.v1.ExpireMachineRequest
(*DeleteMachineRequest)(nil), // 31: ionscale.v1.DeleteMachineRequest
(*SetMachineKeyExpiryRequest)(nil), // 32: ionscale.v1.SetMachineKeyExpiryRequest
(*GetMachineRoutesRequest)(nil), // 33: ionscale.v1.GetMachineRoutesRequest
(*EnableMachineRoutesRequest)(nil), // 34: ionscale.v1.EnableMachineRoutesRequest
(*DisableMachineRoutesRequest)(nil), // 35: ionscale.v1.DisableMachineRoutesRequest
(*EnableExitNodeRequest)(nil), // 36: ionscale.v1.EnableExitNodeRequest
(*DisableExitNodeRequest)(nil), // 37: ionscale.v1.DisableExitNodeRequest
(*EnableHttpsCertificatesRequest)(nil), // 38: ionscale.v1.EnableHttpsCertificatesRequest
(*DisableHttpsCertificatesRequest)(nil), // 39: ionscale.v1.DisableHttpsCertificatesRequest
(*GetVersionResponse)(nil), // 40: ionscale.v1.GetVersionResponse
(*AuthenticationResponse)(nil), // 41: ionscale.v1.AuthenticationResponse
(*GetDefaultDERPMapResponse)(nil), // 42: ionscale.v1.GetDefaultDERPMapResponse
(*SetDefaultDERPMapResponse)(nil), // 43: ionscale.v1.SetDefaultDERPMapResponse
(*ResetDefaultDERPMapResponse)(nil), // 44: ionscale.v1.ResetDefaultDERPMapResponse
(*CreateTailnetResponse)(nil), // 45: ionscale.v1.CreateTailnetResponse
(*GetTailnetResponse)(nil), // 46: ionscale.v1.GetTailnetResponse
(*ListTailnetResponse)(nil), // 47: ionscale.v1.ListTailnetResponse
(*DeleteTailnetResponse)(nil), // 48: ionscale.v1.DeleteTailnetResponse
(*GetDERPMapResponse)(nil), // 49: ionscale.v1.GetDERPMapResponse
(*SetDERPMapResponse)(nil), // 50: ionscale.v1.SetDERPMapResponse
(*ResetDERPMapResponse)(nil), // 51: ionscale.v1.ResetDERPMapResponse
(*EnableFileSharingResponse)(nil), // 52: ionscale.v1.EnableFileSharingResponse
(*DisableFileSharingResponse)(nil), // 53: ionscale.v1.DisableFileSharingResponse
(*EnableServiceCollectionResponse)(nil), // 54: ionscale.v1.EnableServiceCollectionResponse
(*DisableServiceCollectionResponse)(nil), // 55: ionscale.v1.DisableServiceCollectionResponse
(*GetDNSConfigResponse)(nil), // 56: ionscale.v1.GetDNSConfigResponse
(*SetDNSConfigResponse)(nil), // 57: ionscale.v1.SetDNSConfigResponse
(*GetIAMPolicyResponse)(nil), // 58: ionscale.v1.GetIAMPolicyResponse
(*SetIAMPolicyResponse)(nil), // 59: ionscale.v1.SetIAMPolicyResponse
(*GetACLPolicyResponse)(nil), // 60: ionscale.v1.GetACLPolicyResponse
(*SetACLPolicyResponse)(nil), // 61: ionscale.v1.SetACLPolicyResponse
(*GetAuthKeyResponse)(nil), // 62: ionscale.v1.GetAuthKeyResponse
(*CreateAuthKeyResponse)(nil), // 63: ionscale.v1.CreateAuthKeyResponse
(*DeleteAuthKeyResponse)(nil), // 64: ionscale.v1.DeleteAuthKeyResponse
(*ListAuthKeysResponse)(nil), // 65: ionscale.v1.ListAuthKeysResponse
(*ListUsersResponse)(nil), // 66: ionscale.v1.ListUsersResponse
(*DeleteUserResponse)(nil), // 67: ionscale.v1.DeleteUserResponse
(*GetMachineResponse)(nil), // 68: ionscale.v1.GetMachineResponse
(*ListMachinesResponse)(nil), // 69: ionscale.v1.ListMachinesResponse
(*ExpireMachineResponse)(nil), // 70: ionscale.v1.ExpireMachineResponse
(*DeleteMachineResponse)(nil), // 71: ionscale.v1.DeleteMachineResponse
(*SetMachineKeyExpiryResponse)(nil), // 72: ionscale.v1.SetMachineKeyExpiryResponse
(*GetMachineRoutesResponse)(nil), // 73: ionscale.v1.GetMachineRoutesResponse
(*EnableHttpsCertificatesResponse)(nil), // 74: ionscale.v1.EnableHttpsCertificatesResponse
(*DisableHttpsCertificatesResponse)(nil), // 75: ionscale.v1.DisableHttpsCertificatesResponse
(*EnableSSHRequest)(nil), // 16: ionscale.v1.EnableSSHRequest
(*DisableSSHRequest)(nil), // 17: ionscale.v1.DisableSSHRequest
(*GetDNSConfigRequest)(nil), // 18: ionscale.v1.GetDNSConfigRequest
(*SetDNSConfigRequest)(nil), // 19: ionscale.v1.SetDNSConfigRequest
(*GetIAMPolicyRequest)(nil), // 20: ionscale.v1.GetIAMPolicyRequest
(*SetIAMPolicyRequest)(nil), // 21: ionscale.v1.SetIAMPolicyRequest
(*GetACLPolicyRequest)(nil), // 22: ionscale.v1.GetACLPolicyRequest
(*SetACLPolicyRequest)(nil), // 23: ionscale.v1.SetACLPolicyRequest
(*GetAuthKeyRequest)(nil), // 24: ionscale.v1.GetAuthKeyRequest
(*CreateAuthKeyRequest)(nil), // 25: ionscale.v1.CreateAuthKeyRequest
(*DeleteAuthKeyRequest)(nil), // 26: ionscale.v1.DeleteAuthKeyRequest
(*ListAuthKeysRequest)(nil), // 27: ionscale.v1.ListAuthKeysRequest
(*ListUsersRequest)(nil), // 28: ionscale.v1.ListUsersRequest
(*DeleteUserRequest)(nil), // 29: ionscale.v1.DeleteUserRequest
(*GetMachineRequest)(nil), // 30: ionscale.v1.GetMachineRequest
(*ListMachinesRequest)(nil), // 31: ionscale.v1.ListMachinesRequest
(*ExpireMachineRequest)(nil), // 32: ionscale.v1.ExpireMachineRequest
(*DeleteMachineRequest)(nil), // 33: ionscale.v1.DeleteMachineRequest
(*SetMachineKeyExpiryRequest)(nil), // 34: ionscale.v1.SetMachineKeyExpiryRequest
(*GetMachineRoutesRequest)(nil), // 35: ionscale.v1.GetMachineRoutesRequest
(*EnableMachineRoutesRequest)(nil), // 36: ionscale.v1.EnableMachineRoutesRequest
(*DisableMachineRoutesRequest)(nil), // 37: ionscale.v1.DisableMachineRoutesRequest
(*EnableExitNodeRequest)(nil), // 38: ionscale.v1.EnableExitNodeRequest
(*DisableExitNodeRequest)(nil), // 39: ionscale.v1.DisableExitNodeRequest
(*EnableHttpsCertificatesRequest)(nil), // 40: ionscale.v1.EnableHttpsCertificatesRequest
(*DisableHttpsCertificatesRequest)(nil), // 41: ionscale.v1.DisableHttpsCertificatesRequest
(*GetVersionResponse)(nil), // 42: ionscale.v1.GetVersionResponse
(*AuthenticationResponse)(nil), // 43: ionscale.v1.AuthenticationResponse
(*GetDefaultDERPMapResponse)(nil), // 44: ionscale.v1.GetDefaultDERPMapResponse
(*SetDefaultDERPMapResponse)(nil), // 45: ionscale.v1.SetDefaultDERPMapResponse
(*ResetDefaultDERPMapResponse)(nil), // 46: ionscale.v1.ResetDefaultDERPMapResponse
(*CreateTailnetResponse)(nil), // 47: ionscale.v1.CreateTailnetResponse
(*GetTailnetResponse)(nil), // 48: ionscale.v1.GetTailnetResponse
(*ListTailnetResponse)(nil), // 49: ionscale.v1.ListTailnetResponse
(*DeleteTailnetResponse)(nil), // 50: ionscale.v1.DeleteTailnetResponse
(*GetDERPMapResponse)(nil), // 51: ionscale.v1.GetDERPMapResponse
(*SetDERPMapResponse)(nil), // 52: ionscale.v1.SetDERPMapResponse
(*ResetDERPMapResponse)(nil), // 53: ionscale.v1.ResetDERPMapResponse
(*EnableFileSharingResponse)(nil), // 54: ionscale.v1.EnableFileSharingResponse
(*DisableFileSharingResponse)(nil), // 55: ionscale.v1.DisableFileSharingResponse
(*EnableServiceCollectionResponse)(nil), // 56: ionscale.v1.EnableServiceCollectionResponse
(*DisableServiceCollectionResponse)(nil), // 57: ionscale.v1.DisableServiceCollectionResponse
(*EnableSSHResponse)(nil), // 58: ionscale.v1.EnableSSHResponse
(*DisableSSHResponse)(nil), // 59: ionscale.v1.DisableSSHResponse
(*GetDNSConfigResponse)(nil), // 60: ionscale.v1.GetDNSConfigResponse
(*SetDNSConfigResponse)(nil), // 61: ionscale.v1.SetDNSConfigResponse
(*GetIAMPolicyResponse)(nil), // 62: ionscale.v1.GetIAMPolicyResponse
(*SetIAMPolicyResponse)(nil), // 63: ionscale.v1.SetIAMPolicyResponse
(*GetACLPolicyResponse)(nil), // 64: ionscale.v1.GetACLPolicyResponse
(*SetACLPolicyResponse)(nil), // 65: ionscale.v1.SetACLPolicyResponse
(*GetAuthKeyResponse)(nil), // 66: ionscale.v1.GetAuthKeyResponse
(*CreateAuthKeyResponse)(nil), // 67: ionscale.v1.CreateAuthKeyResponse
(*DeleteAuthKeyResponse)(nil), // 68: ionscale.v1.DeleteAuthKeyResponse
(*ListAuthKeysResponse)(nil), // 69: ionscale.v1.ListAuthKeysResponse
(*ListUsersResponse)(nil), // 70: ionscale.v1.ListUsersResponse
(*DeleteUserResponse)(nil), // 71: ionscale.v1.DeleteUserResponse
(*GetMachineResponse)(nil), // 72: ionscale.v1.GetMachineResponse
(*ListMachinesResponse)(nil), // 73: ionscale.v1.ListMachinesResponse
(*ExpireMachineResponse)(nil), // 74: ionscale.v1.ExpireMachineResponse
(*DeleteMachineResponse)(nil), // 75: ionscale.v1.DeleteMachineResponse
(*SetMachineKeyExpiryResponse)(nil), // 76: ionscale.v1.SetMachineKeyExpiryResponse
(*GetMachineRoutesResponse)(nil), // 77: ionscale.v1.GetMachineRoutesResponse
(*EnableHttpsCertificatesResponse)(nil), // 78: ionscale.v1.EnableHttpsCertificatesResponse
(*DisableHttpsCertificatesResponse)(nil), // 79: ionscale.v1.DisableHttpsCertificatesResponse
}
var file_ionscale_v1_ionscale_proto_depIdxs = []int32{
0, // 0: ionscale.v1.IonscaleService.GetVersion:input_type -> ionscale.v1.GetVersionRequest
@@ -387,72 +401,76 @@ var file_ionscale_v1_ionscale_proto_depIdxs = []int32{
13, // 13: ionscale.v1.IonscaleService.DisableFileSharing:input_type -> ionscale.v1.DisableFileSharingRequest
14, // 14: ionscale.v1.IonscaleService.EnabledServiceCollection:input_type -> ionscale.v1.EnableServiceCollectionRequest
15, // 15: ionscale.v1.IonscaleService.DisableServiceCollection:input_type -> ionscale.v1.DisableServiceCollectionRequest
16, // 16: ionscale.v1.IonscaleService.GetDNSConfig:input_type -> ionscale.v1.GetDNSConfigRequest
17, // 17: ionscale.v1.IonscaleService.SetDNSConfig:input_type -> ionscale.v1.SetDNSConfigRequest
18, // 18: ionscale.v1.IonscaleService.GetIAMPolicy:input_type -> ionscale.v1.GetIAMPolicyRequest
19, // 19: ionscale.v1.IonscaleService.SetIAMPolicy:input_type -> ionscale.v1.SetIAMPolicyRequest
20, // 20: ionscale.v1.IonscaleService.GetACLPolicy:input_type -> ionscale.v1.GetACLPolicyRequest
21, // 21: ionscale.v1.IonscaleService.SetACLPolicy:input_type -> ionscale.v1.SetACLPolicyRequest
22, // 22: ionscale.v1.IonscaleService.GetAuthKey:input_type -> ionscale.v1.GetAuthKeyRequest
23, // 23: ionscale.v1.IonscaleService.CreateAuthKey:input_type -> ionscale.v1.CreateAuthKeyRequest
24, // 24: ionscale.v1.IonscaleService.DeleteAuthKey:input_type -> ionscale.v1.DeleteAuthKeyRequest
25, // 25: ionscale.v1.IonscaleService.ListAuthKeys:input_type -> ionscale.v1.ListAuthKeysRequest
26, // 26: ionscale.v1.IonscaleService.ListUsers:input_type -> ionscale.v1.ListUsersRequest
27, // 27: ionscale.v1.IonscaleService.DeleteUser:input_type -> ionscale.v1.DeleteUserRequest
28, // 28: ionscale.v1.IonscaleService.GetMachine:input_type -> ionscale.v1.GetMachineRequest
29, // 29: ionscale.v1.IonscaleService.ListMachines:input_type -> ionscale.v1.ListMachinesRequest
30, // 30: ionscale.v1.IonscaleService.ExpireMachine:input_type -> ionscale.v1.ExpireMachineRequest
31, // 31: ionscale.v1.IonscaleService.DeleteMachine:input_type -> ionscale.v1.DeleteMachineRequest
32, // 32: ionscale.v1.IonscaleService.SetMachineKeyExpiry:input_type -> ionscale.v1.SetMachineKeyExpiryRequest
33, // 33: ionscale.v1.IonscaleService.GetMachineRoutes:input_type -> ionscale.v1.GetMachineRoutesRequest
34, // 34: ionscale.v1.IonscaleService.EnableMachineRoutes:input_type -> ionscale.v1.EnableMachineRoutesRequest
35, // 35: ionscale.v1.IonscaleService.DisableMachineRoutes:input_type -> ionscale.v1.DisableMachineRoutesRequest
36, // 36: ionscale.v1.IonscaleService.EnableExitNode:input_type -> ionscale.v1.EnableExitNodeRequest
37, // 37: ionscale.v1.IonscaleService.DisableExitNode:input_type -> ionscale.v1.DisableExitNodeRequest
38, // 38: ionscale.v1.IonscaleService.EnableHttpsCertificates:input_type -> ionscale.v1.EnableHttpsCertificatesRequest
39, // 39: ionscale.v1.IonscaleService.DisableHttpsCertificates:input_type -> ionscale.v1.DisableHttpsCertificatesRequest
40, // 40: ionscale.v1.IonscaleService.GetVersion:output_type -> ionscale.v1.GetVersionResponse
41, // 41: ionscale.v1.IonscaleService.Authenticate:output_type -> ionscale.v1.AuthenticationResponse
42, // 42: ionscale.v1.IonscaleService.GetDefaultDERPMap:output_type -> ionscale.v1.GetDefaultDERPMapResponse
43, // 43: ionscale.v1.IonscaleService.SetDefaultDERPMap:output_type -> ionscale.v1.SetDefaultDERPMapResponse
44, // 44: ionscale.v1.IonscaleService.ResetDefaultDERPMap:output_type -> ionscale.v1.ResetDefaultDERPMapResponse
45, // 45: ionscale.v1.IonscaleService.CreateTailnet:output_type -> ionscale.v1.CreateTailnetResponse
46, // 46: ionscale.v1.IonscaleService.GetTailnet:output_type -> ionscale.v1.GetTailnetResponse
47, // 47: ionscale.v1.IonscaleService.ListTailnets:output_type -> ionscale.v1.ListTailnetResponse
48, // 48: ionscale.v1.IonscaleService.DeleteTailnet:output_type -> ionscale.v1.DeleteTailnetResponse
49, // 49: ionscale.v1.IonscaleService.GetDERPMap:output_type -> ionscale.v1.GetDERPMapResponse
50, // 50: ionscale.v1.IonscaleService.SetDERPMap:output_type -> ionscale.v1.SetDERPMapResponse
51, // 51: ionscale.v1.IonscaleService.ResetDERPMap:output_type -> ionscale.v1.ResetDERPMapResponse
52, // 52: ionscale.v1.IonscaleService.EnabledFileSharing:output_type -> ionscale.v1.EnableFileSharingResponse
53, // 53: ionscale.v1.IonscaleService.DisableFileSharing:output_type -> ionscale.v1.DisableFileSharingResponse
54, // 54: ionscale.v1.IonscaleService.EnabledServiceCollection:output_type -> ionscale.v1.EnableServiceCollectionResponse
55, // 55: ionscale.v1.IonscaleService.DisableServiceCollection:output_type -> ionscale.v1.DisableServiceCollectionResponse
56, // 56: ionscale.v1.IonscaleService.GetDNSConfig:output_type -> ionscale.v1.GetDNSConfigResponse
57, // 57: ionscale.v1.IonscaleService.SetDNSConfig:output_type -> ionscale.v1.SetDNSConfigResponse
58, // 58: ionscale.v1.IonscaleService.GetIAMPolicy:output_type -> ionscale.v1.GetIAMPolicyResponse
59, // 59: ionscale.v1.IonscaleService.SetIAMPolicy:output_type -> ionscale.v1.SetIAMPolicyResponse
60, // 60: ionscale.v1.IonscaleService.GetACLPolicy:output_type -> ionscale.v1.GetACLPolicyResponse
61, // 61: ionscale.v1.IonscaleService.SetACLPolicy:output_type -> ionscale.v1.SetACLPolicyResponse
62, // 62: ionscale.v1.IonscaleService.GetAuthKey:output_type -> ionscale.v1.GetAuthKeyResponse
63, // 63: ionscale.v1.IonscaleService.CreateAuthKey:output_type -> ionscale.v1.CreateAuthKeyResponse
64, // 64: ionscale.v1.IonscaleService.DeleteAuthKey:output_type -> ionscale.v1.DeleteAuthKeyResponse
65, // 65: ionscale.v1.IonscaleService.ListAuthKeys:output_type -> ionscale.v1.ListAuthKeysResponse
66, // 66: ionscale.v1.IonscaleService.ListUsers:output_type -> ionscale.v1.ListUsersResponse
67, // 67: ionscale.v1.IonscaleService.DeleteUser:output_type -> ionscale.v1.DeleteUserResponse
68, // 68: ionscale.v1.IonscaleService.GetMachine:output_type -> ionscale.v1.GetMachineResponse
69, // 69: ionscale.v1.IonscaleService.ListMachines:output_type -> ionscale.v1.ListMachinesResponse
70, // 70: ionscale.v1.IonscaleService.ExpireMachine:output_type -> ionscale.v1.ExpireMachineResponse
71, // 71: ionscale.v1.IonscaleService.DeleteMachine:output_type -> ionscale.v1.DeleteMachineResponse
72, // 72: ionscale.v1.IonscaleService.SetMachineKeyExpiry:output_type -> ionscale.v1.SetMachineKeyExpiryResponse
73, // 73: ionscale.v1.IonscaleService.GetMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
73, // 74: ionscale.v1.IonscaleService.EnableMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
73, // 75: ionscale.v1.IonscaleService.DisableMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
73, // 76: ionscale.v1.IonscaleService.EnableExitNode:output_type -> ionscale.v1.GetMachineRoutesResponse
73, // 77: ionscale.v1.IonscaleService.DisableExitNode:output_type -> ionscale.v1.GetMachineRoutesResponse
74, // 78: ionscale.v1.IonscaleService.EnableHttpsCertificates:output_type -> ionscale.v1.EnableHttpsCertificatesResponse
75, // 79: ionscale.v1.IonscaleService.DisableHttpsCertificates:output_type -> ionscale.v1.DisableHttpsCertificatesResponse
40, // [40:80] is the sub-list for method output_type
0, // [0:40] is the sub-list for method input_type
16, // 16: ionscale.v1.IonscaleService.EnabledSSH:input_type -> ionscale.v1.EnableSSHRequest
17, // 17: ionscale.v1.IonscaleService.DisableSSH:input_type -> ionscale.v1.DisableSSHRequest
18, // 18: ionscale.v1.IonscaleService.GetDNSConfig:input_type -> ionscale.v1.GetDNSConfigRequest
19, // 19: ionscale.v1.IonscaleService.SetDNSConfig:input_type -> ionscale.v1.SetDNSConfigRequest
20, // 20: ionscale.v1.IonscaleService.GetIAMPolicy:input_type -> ionscale.v1.GetIAMPolicyRequest
21, // 21: ionscale.v1.IonscaleService.SetIAMPolicy:input_type -> ionscale.v1.SetIAMPolicyRequest
22, // 22: ionscale.v1.IonscaleService.GetACLPolicy:input_type -> ionscale.v1.GetACLPolicyRequest
23, // 23: ionscale.v1.IonscaleService.SetACLPolicy:input_type -> ionscale.v1.SetACLPolicyRequest
24, // 24: ionscale.v1.IonscaleService.GetAuthKey:input_type -> ionscale.v1.GetAuthKeyRequest
25, // 25: ionscale.v1.IonscaleService.CreateAuthKey:input_type -> ionscale.v1.CreateAuthKeyRequest
26, // 26: ionscale.v1.IonscaleService.DeleteAuthKey:input_type -> ionscale.v1.DeleteAuthKeyRequest
27, // 27: ionscale.v1.IonscaleService.ListAuthKeys:input_type -> ionscale.v1.ListAuthKeysRequest
28, // 28: ionscale.v1.IonscaleService.ListUsers:input_type -> ionscale.v1.ListUsersRequest
29, // 29: ionscale.v1.IonscaleService.DeleteUser:input_type -> ionscale.v1.DeleteUserRequest
30, // 30: ionscale.v1.IonscaleService.GetMachine:input_type -> ionscale.v1.GetMachineRequest
31, // 31: ionscale.v1.IonscaleService.ListMachines:input_type -> ionscale.v1.ListMachinesRequest
32, // 32: ionscale.v1.IonscaleService.ExpireMachine:input_type -> ionscale.v1.ExpireMachineRequest
33, // 33: ionscale.v1.IonscaleService.DeleteMachine:input_type -> ionscale.v1.DeleteMachineRequest
34, // 34: ionscale.v1.IonscaleService.SetMachineKeyExpiry:input_type -> ionscale.v1.SetMachineKeyExpiryRequest
35, // 35: ionscale.v1.IonscaleService.GetMachineRoutes:input_type -> ionscale.v1.GetMachineRoutesRequest
36, // 36: ionscale.v1.IonscaleService.EnableMachineRoutes:input_type -> ionscale.v1.EnableMachineRoutesRequest
37, // 37: ionscale.v1.IonscaleService.DisableMachineRoutes:input_type -> ionscale.v1.DisableMachineRoutesRequest
38, // 38: ionscale.v1.IonscaleService.EnableExitNode:input_type -> ionscale.v1.EnableExitNodeRequest
39, // 39: ionscale.v1.IonscaleService.DisableExitNode:input_type -> ionscale.v1.DisableExitNodeRequest
40, // 40: ionscale.v1.IonscaleService.EnableHttpsCertificates:input_type -> ionscale.v1.EnableHttpsCertificatesRequest
41, // 41: ionscale.v1.IonscaleService.DisableHttpsCertificates:input_type -> ionscale.v1.DisableHttpsCertificatesRequest
42, // 42: ionscale.v1.IonscaleService.GetVersion:output_type -> ionscale.v1.GetVersionResponse
43, // 43: ionscale.v1.IonscaleService.Authenticate:output_type -> ionscale.v1.AuthenticationResponse
44, // 44: ionscale.v1.IonscaleService.GetDefaultDERPMap:output_type -> ionscale.v1.GetDefaultDERPMapResponse
45, // 45: ionscale.v1.IonscaleService.SetDefaultDERPMap:output_type -> ionscale.v1.SetDefaultDERPMapResponse
46, // 46: ionscale.v1.IonscaleService.ResetDefaultDERPMap:output_type -> ionscale.v1.ResetDefaultDERPMapResponse
47, // 47: ionscale.v1.IonscaleService.CreateTailnet:output_type -> ionscale.v1.CreateTailnetResponse
48, // 48: ionscale.v1.IonscaleService.GetTailnet:output_type -> ionscale.v1.GetTailnetResponse
49, // 49: ionscale.v1.IonscaleService.ListTailnets:output_type -> ionscale.v1.ListTailnetResponse
50, // 50: ionscale.v1.IonscaleService.DeleteTailnet:output_type -> ionscale.v1.DeleteTailnetResponse
51, // 51: ionscale.v1.IonscaleService.GetDERPMap:output_type -> ionscale.v1.GetDERPMapResponse
52, // 52: ionscale.v1.IonscaleService.SetDERPMap:output_type -> ionscale.v1.SetDERPMapResponse
53, // 53: ionscale.v1.IonscaleService.ResetDERPMap:output_type -> ionscale.v1.ResetDERPMapResponse
54, // 54: ionscale.v1.IonscaleService.EnabledFileSharing:output_type -> ionscale.v1.EnableFileSharingResponse
55, // 55: ionscale.v1.IonscaleService.DisableFileSharing:output_type -> ionscale.v1.DisableFileSharingResponse
56, // 56: ionscale.v1.IonscaleService.EnabledServiceCollection:output_type -> ionscale.v1.EnableServiceCollectionResponse
57, // 57: ionscale.v1.IonscaleService.DisableServiceCollection:output_type -> ionscale.v1.DisableServiceCollectionResponse
58, // 58: ionscale.v1.IonscaleService.EnabledSSH:output_type -> ionscale.v1.EnableSSHResponse
59, // 59: ionscale.v1.IonscaleService.DisableSSH:output_type -> ionscale.v1.DisableSSHResponse
60, // 60: ionscale.v1.IonscaleService.GetDNSConfig:output_type -> ionscale.v1.GetDNSConfigResponse
61, // 61: ionscale.v1.IonscaleService.SetDNSConfig:output_type -> ionscale.v1.SetDNSConfigResponse
62, // 62: ionscale.v1.IonscaleService.GetIAMPolicy:output_type -> ionscale.v1.GetIAMPolicyResponse
63, // 63: ionscale.v1.IonscaleService.SetIAMPolicy:output_type -> ionscale.v1.SetIAMPolicyResponse
64, // 64: ionscale.v1.IonscaleService.GetACLPolicy:output_type -> ionscale.v1.GetACLPolicyResponse
65, // 65: ionscale.v1.IonscaleService.SetACLPolicy:output_type -> ionscale.v1.SetACLPolicyResponse
66, // 66: ionscale.v1.IonscaleService.GetAuthKey:output_type -> ionscale.v1.GetAuthKeyResponse
67, // 67: ionscale.v1.IonscaleService.CreateAuthKey:output_type -> ionscale.v1.CreateAuthKeyResponse
68, // 68: ionscale.v1.IonscaleService.DeleteAuthKey:output_type -> ionscale.v1.DeleteAuthKeyResponse
69, // 69: ionscale.v1.IonscaleService.ListAuthKeys:output_type -> ionscale.v1.ListAuthKeysResponse
70, // 70: ionscale.v1.IonscaleService.ListUsers:output_type -> ionscale.v1.ListUsersResponse
71, // 71: ionscale.v1.IonscaleService.DeleteUser:output_type -> ionscale.v1.DeleteUserResponse
72, // 72: ionscale.v1.IonscaleService.GetMachine:output_type -> ionscale.v1.GetMachineResponse
73, // 73: ionscale.v1.IonscaleService.ListMachines:output_type -> ionscale.v1.ListMachinesResponse
74, // 74: ionscale.v1.IonscaleService.ExpireMachine:output_type -> ionscale.v1.ExpireMachineResponse
75, // 75: ionscale.v1.IonscaleService.DeleteMachine:output_type -> ionscale.v1.DeleteMachineResponse
76, // 76: ionscale.v1.IonscaleService.SetMachineKeyExpiry:output_type -> ionscale.v1.SetMachineKeyExpiryResponse
77, // 77: ionscale.v1.IonscaleService.GetMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
77, // 78: ionscale.v1.IonscaleService.EnableMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
77, // 79: ionscale.v1.IonscaleService.DisableMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
77, // 80: ionscale.v1.IonscaleService.EnableExitNode:output_type -> ionscale.v1.GetMachineRoutesResponse
77, // 81: ionscale.v1.IonscaleService.DisableExitNode:output_type -> ionscale.v1.GetMachineRoutesResponse
78, // 82: ionscale.v1.IonscaleService.EnableHttpsCertificates:output_type -> ionscale.v1.EnableHttpsCertificatesResponse
79, // 83: ionscale.v1.IonscaleService.DisableHttpsCertificates:output_type -> ionscale.v1.DisableHttpsCertificatesResponse
42, // [42:84] is the sub-list for method output_type
0, // [0:42] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -43,6 +43,8 @@ type IonscaleServiceClient interface {
DisableFileSharing(context.Context, *connect_go.Request[v1.DisableFileSharingRequest]) (*connect_go.Response[v1.DisableFileSharingResponse], error)
EnabledServiceCollection(context.Context, *connect_go.Request[v1.EnableServiceCollectionRequest]) (*connect_go.Response[v1.EnableServiceCollectionResponse], error)
DisableServiceCollection(context.Context, *connect_go.Request[v1.DisableServiceCollectionRequest]) (*connect_go.Response[v1.DisableServiceCollectionResponse], error)
EnabledSSH(context.Context, *connect_go.Request[v1.EnableSSHRequest]) (*connect_go.Response[v1.EnableSSHResponse], error)
DisableSSH(context.Context, *connect_go.Request[v1.DisableSSHRequest]) (*connect_go.Response[v1.DisableSSHResponse], error)
GetDNSConfig(context.Context, *connect_go.Request[v1.GetDNSConfigRequest]) (*connect_go.Response[v1.GetDNSConfigResponse], error)
SetDNSConfig(context.Context, *connect_go.Request[v1.SetDNSConfigRequest]) (*connect_go.Response[v1.SetDNSConfigResponse], error)
GetIAMPolicy(context.Context, *connect_go.Request[v1.GetIAMPolicyRequest]) (*connect_go.Response[v1.GetIAMPolicyResponse], error)
@@ -159,6 +161,16 @@ func NewIonscaleServiceClient(httpClient connect_go.HTTPClient, baseURL string,
baseURL+"/ionscale.v1.IonscaleService/DisableServiceCollection",
opts...,
),
enabledSSH: connect_go.NewClient[v1.EnableSSHRequest, v1.EnableSSHResponse](
httpClient,
baseURL+"/ionscale.v1.IonscaleService/EnabledSSH",
opts...,
),
disableSSH: connect_go.NewClient[v1.DisableSSHRequest, v1.DisableSSHResponse](
httpClient,
baseURL+"/ionscale.v1.IonscaleService/DisableSSH",
opts...,
),
getDNSConfig: connect_go.NewClient[v1.GetDNSConfigRequest, v1.GetDNSConfigResponse](
httpClient,
baseURL+"/ionscale.v1.IonscaleService/GetDNSConfig",
@@ -300,6 +312,8 @@ type ionscaleServiceClient struct {
disableFileSharing *connect_go.Client[v1.DisableFileSharingRequest, v1.DisableFileSharingResponse]
enabledServiceCollection *connect_go.Client[v1.EnableServiceCollectionRequest, v1.EnableServiceCollectionResponse]
disableServiceCollection *connect_go.Client[v1.DisableServiceCollectionRequest, v1.DisableServiceCollectionResponse]
enabledSSH *connect_go.Client[v1.EnableSSHRequest, v1.EnableSSHResponse]
disableSSH *connect_go.Client[v1.DisableSSHRequest, v1.DisableSSHResponse]
getDNSConfig *connect_go.Client[v1.GetDNSConfigRequest, v1.GetDNSConfigResponse]
setDNSConfig *connect_go.Client[v1.SetDNSConfigRequest, v1.SetDNSConfigResponse]
getIAMPolicy *connect_go.Client[v1.GetIAMPolicyRequest, v1.GetIAMPolicyResponse]
@@ -406,6 +420,16 @@ func (c *ionscaleServiceClient) DisableServiceCollection(ctx context.Context, re
return c.disableServiceCollection.CallUnary(ctx, req)
}
// EnabledSSH calls ionscale.v1.IonscaleService.EnabledSSH.
func (c *ionscaleServiceClient) EnabledSSH(ctx context.Context, req *connect_go.Request[v1.EnableSSHRequest]) (*connect_go.Response[v1.EnableSSHResponse], error) {
return c.enabledSSH.CallUnary(ctx, req)
}
// DisableSSH calls ionscale.v1.IonscaleService.DisableSSH.
func (c *ionscaleServiceClient) DisableSSH(ctx context.Context, req *connect_go.Request[v1.DisableSSHRequest]) (*connect_go.Response[v1.DisableSSHResponse], error) {
return c.disableSSH.CallUnary(ctx, req)
}
// GetDNSConfig calls ionscale.v1.IonscaleService.GetDNSConfig.
func (c *ionscaleServiceClient) GetDNSConfig(ctx context.Context, req *connect_go.Request[v1.GetDNSConfigRequest]) (*connect_go.Response[v1.GetDNSConfigResponse], error) {
return c.getDNSConfig.CallUnary(ctx, req)
@@ -544,6 +568,8 @@ type IonscaleServiceHandler interface {
DisableFileSharing(context.Context, *connect_go.Request[v1.DisableFileSharingRequest]) (*connect_go.Response[v1.DisableFileSharingResponse], error)
EnabledServiceCollection(context.Context, *connect_go.Request[v1.EnableServiceCollectionRequest]) (*connect_go.Response[v1.EnableServiceCollectionResponse], error)
DisableServiceCollection(context.Context, *connect_go.Request[v1.DisableServiceCollectionRequest]) (*connect_go.Response[v1.DisableServiceCollectionResponse], error)
EnabledSSH(context.Context, *connect_go.Request[v1.EnableSSHRequest]) (*connect_go.Response[v1.EnableSSHResponse], error)
DisableSSH(context.Context, *connect_go.Request[v1.DisableSSHRequest]) (*connect_go.Response[v1.DisableSSHResponse], error)
GetDNSConfig(context.Context, *connect_go.Request[v1.GetDNSConfigRequest]) (*connect_go.Response[v1.GetDNSConfigResponse], error)
SetDNSConfig(context.Context, *connect_go.Request[v1.SetDNSConfigRequest]) (*connect_go.Response[v1.SetDNSConfigResponse], error)
GetIAMPolicy(context.Context, *connect_go.Request[v1.GetIAMPolicyRequest]) (*connect_go.Response[v1.GetIAMPolicyResponse], error)
@@ -657,6 +683,16 @@ func NewIonscaleServiceHandler(svc IonscaleServiceHandler, opts ...connect_go.Ha
svc.DisableServiceCollection,
opts...,
))
mux.Handle("/ionscale.v1.IonscaleService/EnabledSSH", connect_go.NewUnaryHandler(
"/ionscale.v1.IonscaleService/EnabledSSH",
svc.EnabledSSH,
opts...,
))
mux.Handle("/ionscale.v1.IonscaleService/DisableSSH", connect_go.NewUnaryHandler(
"/ionscale.v1.IonscaleService/DisableSSH",
svc.DisableSSH,
opts...,
))
mux.Handle("/ionscale.v1.IonscaleService/GetDNSConfig", connect_go.NewUnaryHandler(
"/ionscale.v1.IonscaleService/GetDNSConfig",
svc.GetDNSConfig,
@@ -847,6 +883,14 @@ func (UnimplementedIonscaleServiceHandler) DisableServiceCollection(context.Cont
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.DisableServiceCollection is not implemented"))
}
func (UnimplementedIonscaleServiceHandler) EnabledSSH(context.Context, *connect_go.Request[v1.EnableSSHRequest]) (*connect_go.Response[v1.EnableSSHResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.EnabledSSH is not implemented"))
}
func (UnimplementedIonscaleServiceHandler) DisableSSH(context.Context, *connect_go.Request[v1.DisableSSHRequest]) (*connect_go.Response[v1.DisableSSHResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.DisableSSH is not implemented"))
}
func (UnimplementedIonscaleServiceHandler) GetDNSConfig(context.Context, *connect_go.Request[v1.GetDNSConfigRequest]) (*connect_go.Response[v1.GetDNSConfigResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.GetDNSConfig is not implemented"))
}
+241 -9
View File
@@ -1070,6 +1070,176 @@ func (*DisableServiceCollectionResponse) Descriptor() ([]byte, []int) {
return file_ionscale_v1_tailnets_proto_rawDescGZIP(), []int{22}
}
type EnableSSHRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
}
func (x *EnableSSHRequest) Reset() {
*x = EnableSSHRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableSSHRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EnableSSHRequest) ProtoMessage() {}
func (x *EnableSSHRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[23]
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 EnableSSHRequest.ProtoReflect.Descriptor instead.
func (*EnableSSHRequest) Descriptor() ([]byte, []int) {
return file_ionscale_v1_tailnets_proto_rawDescGZIP(), []int{23}
}
func (x *EnableSSHRequest) GetTailnetId() uint64 {
if x != nil {
return x.TailnetId
}
return 0
}
type EnableSSHResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *EnableSSHResponse) Reset() {
*x = EnableSSHResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableSSHResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EnableSSHResponse) ProtoMessage() {}
func (x *EnableSSHResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[24]
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 EnableSSHResponse.ProtoReflect.Descriptor instead.
func (*EnableSSHResponse) Descriptor() ([]byte, []int) {
return file_ionscale_v1_tailnets_proto_rawDescGZIP(), []int{24}
}
type DisableSSHRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
}
func (x *DisableSSHRequest) Reset() {
*x = DisableSSHRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableSSHRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DisableSSHRequest) ProtoMessage() {}
func (x *DisableSSHRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[25]
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 DisableSSHRequest.ProtoReflect.Descriptor instead.
func (*DisableSSHRequest) Descriptor() ([]byte, []int) {
return file_ionscale_v1_tailnets_proto_rawDescGZIP(), []int{25}
}
func (x *DisableSSHRequest) GetTailnetId() uint64 {
if x != nil {
return x.TailnetId
}
return 0
}
type DisableSSHResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DisableSSHResponse) Reset() {
*x = DisableSSHResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableSSHResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DisableSSHResponse) ProtoMessage() {}
func (x *DisableSSHResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_tailnets_proto_msgTypes[26]
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 DisableSSHResponse.ProtoReflect.Descriptor instead.
func (*DisableSSHResponse) Descriptor() ([]byte, []int) {
return file_ionscale_v1_tailnets_proto_rawDescGZIP(), []int{26}
}
var File_ionscale_v1_tailnets_proto protoreflect.FileDescriptor
var file_ionscale_v1_tailnets_proto_rawDesc = []byte{
@@ -1151,11 +1321,21 @@ var file_ionscale_v1_tailnets_proto_rawDesc = []byte{
0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x61, 0x69, 0x6c,
0x6e, 0x65, 0x74, 0x49, 0x64, 0x22, 0x22, 0x0a, 0x20, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73,
0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x0a, 0x10, 0x45, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x09, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x22, 0x13, 0x0a, 0x11,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x32, 0x0a, 0x11, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x53, 0x48, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65,
0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x61, 0x69, 0x6c,
0x6e, 0x65, 0x74, 0x49, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x53, 0x53, 0x48, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65,
0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b,
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@@ -1170,7 +1350,7 @@ func file_ionscale_v1_tailnets_proto_rawDescGZIP() []byte {
return file_ionscale_v1_tailnets_proto_rawDescData
}
var file_ionscale_v1_tailnets_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
var file_ionscale_v1_tailnets_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
var file_ionscale_v1_tailnets_proto_goTypes = []interface{}{
(*Tailnet)(nil), // 0: ionscale.v1.Tailnet
(*CreateTailnetRequest)(nil), // 1: ionscale.v1.CreateTailnetRequest
@@ -1195,10 +1375,14 @@ var file_ionscale_v1_tailnets_proto_goTypes = []interface{}{
(*EnableServiceCollectionResponse)(nil), // 20: ionscale.v1.EnableServiceCollectionResponse
(*DisableServiceCollectionRequest)(nil), // 21: ionscale.v1.DisableServiceCollectionRequest
(*DisableServiceCollectionResponse)(nil), // 22: ionscale.v1.DisableServiceCollectionResponse
(*IAMPolicy)(nil), // 23: ionscale.v1.IAMPolicy
(*EnableSSHRequest)(nil), // 23: ionscale.v1.EnableSSHRequest
(*EnableSSHResponse)(nil), // 24: ionscale.v1.EnableSSHResponse
(*DisableSSHRequest)(nil), // 25: ionscale.v1.DisableSSHRequest
(*DisableSSHResponse)(nil), // 26: ionscale.v1.DisableSSHResponse
(*IAMPolicy)(nil), // 27: ionscale.v1.IAMPolicy
}
var file_ionscale_v1_tailnets_proto_depIdxs = []int32{
23, // 0: ionscale.v1.CreateTailnetRequest.iam_policy:type_name -> ionscale.v1.IAMPolicy
27, // 0: ionscale.v1.CreateTailnetRequest.iam_policy:type_name -> ionscale.v1.IAMPolicy
0, // 1: ionscale.v1.CreateTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet
0, // 2: ionscale.v1.GetTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet
0, // 3: ionscale.v1.ListTailnetResponse.tailnet:type_name -> ionscale.v1.Tailnet
@@ -1492,6 +1676,54 @@ func file_ionscale_v1_tailnets_proto_init() {
return nil
}
}
file_ionscale_v1_tailnets_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableSSHRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_tailnets_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableSSHResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_tailnets_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableSSHRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_tailnets_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableSSHResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -1499,7 +1731,7 @@ func file_ionscale_v1_tailnets_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_tailnets_proto_rawDesc,
NumEnums: 0,
NumMessages: 23,
NumMessages: 27,
NumExtensions: 0,
NumServices: 0,
},
+8
View File
@@ -29,6 +29,7 @@ message ACLPolicy {
repeated ACL acls = 3;
map<string, google.protobuf.ListValue> tagowners = 4;
AutoApprovers autoapprovers = 5;
repeated SSHRule ssh = 6;
}
message ACL {
@@ -41,3 +42,10 @@ message AutoApprovers {
map<string, google.protobuf.ListValue> routes = 1;
repeated string exitnode = 2;
}
message SSHRule {
string action = 1;
repeated string src = 2;
repeated string dst = 3;
repeated string users = 4;
}
+2
View File
@@ -38,6 +38,8 @@ service IonscaleService {
rpc DisableFileSharing (DisableFileSharingRequest) returns (DisableFileSharingResponse) {}
rpc EnabledServiceCollection (EnableServiceCollectionRequest) returns (EnableServiceCollectionResponse) {}
rpc DisableServiceCollection (DisableServiceCollectionRequest) returns (DisableServiceCollectionResponse) {}
rpc EnabledSSH (EnableSSHRequest) returns (EnableSSHResponse) {}
rpc DisableSSH (DisableSSHRequest) returns (DisableSSHResponse) {}
rpc GetDNSConfig (GetDNSConfigRequest) returns (GetDNSConfigResponse) {}
rpc SetDNSConfig (SetDNSConfigRequest) returns (SetDNSConfigResponse) {}
+15
View File
@@ -92,3 +92,18 @@ message DisableServiceCollectionRequest {
message DisableServiceCollectionResponse {
}
message EnableSSHRequest {
uint64 tailnet_id = 1;
}
message EnableSSHResponse {
}
message DisableSSHRequest {
uint64 tailnet_id = 1;
}
message DisableSSHResponse {
}