mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 17:53:28 +00:00
Add an installer script resource type and public HTTP endpoint (#13146)
* Add an installer script resource type and HTTP endpoint * Add default installer scripts * Resolve comments - run `shfmt` over the installer script - add MustNewInstaller - move default installer logic to GetInstaller - only include PublicProxyAddr in server.Config * Resolve comments - move from auth_with_roles -> auth/grpcserver - document `MustNewInstallerV1`
This commit is contained in:
parent
321d3482dd
commit
f56dd09ebd
|
@ -2273,6 +2273,31 @@ func (c *Client) GetClusterAuditConfig(ctx context.Context) (types.ClusterAuditC
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// GetInstaller gets the cluster installer resource
|
||||
func (c *Client) GetInstaller(ctx context.Context) (types.Installer, error) {
|
||||
resp, err := c.grpc.GetInstaller(ctx, &empty.Empty{}, c.callOpts...)
|
||||
if err != nil {
|
||||
return nil, trail.FromGRPC(err)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetInstaller sets the cluster installer resource
|
||||
func (c *Client) SetInstaller(ctx context.Context, inst types.Installer) error {
|
||||
instV1, ok := inst.(*types.InstallerV1)
|
||||
if !ok {
|
||||
return trace.BadParameter("invalid type %T", inst)
|
||||
}
|
||||
_, err := c.grpc.SetInstaller(ctx, instV1, c.callOpts...)
|
||||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// GetInstaller deletes the cluster installer resource
|
||||
func (c *Client) DeleteInstaller(ctx context.Context) error {
|
||||
_, err := c.grpc.DeleteInstaller(ctx, &empty.Empty{}, c.callOpts...)
|
||||
return trail.FromGRPC(err)
|
||||
}
|
||||
|
||||
// GetLock gets a lock by name.
|
||||
func (c *Client) GetLock(ctx context.Context, name string) (types.Lock, error) {
|
||||
if name == "" {
|
||||
|
|
|
@ -162,6 +162,10 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
|
|||
out.Resource = &proto.Event_WindowsDesktop{
|
||||
WindowsDesktop: r,
|
||||
}
|
||||
case *types.InstallerV1:
|
||||
out.Resource = &proto.Event_Installer{
|
||||
Installer: r,
|
||||
}
|
||||
default:
|
||||
return nil, trace.BadParameter("resource type %T is not supported", in.Resource)
|
||||
}
|
||||
|
@ -287,6 +291,9 @@ func EventFromGRPC(in proto.Event) (*types.Event, error) {
|
|||
} else if r := in.GetKubernetesCluster(); r != nil {
|
||||
out.Resource = r
|
||||
return &out, nil
|
||||
} else if r := in.GetInstaller(); r != nil {
|
||||
out.Resource = r
|
||||
return &out, nil
|
||||
} else {
|
||||
return nil, trace.BadParameter("received unsupported resource %T", in.Resource)
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -130,6 +130,8 @@ message Event {
|
|||
// KubernetesCluster is an Kubernetes cluster resource.
|
||||
types.KubernetesClusterV3 KubernetesCluster = 33
|
||||
[ (gogoproto.jsontag) = "kubernetes_cluster,omitempty" ];
|
||||
// Installer is an installer resource
|
||||
types.InstallerV1 Installer = 34 [ (gogoproto.jsontag) = "installer,omitempty" ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2535,6 +2537,15 @@ service AuthService {
|
|||
// is used to gain access to privileged actions eg: deleting/adding a MFA device.
|
||||
rpc CreatePrivilegeToken(CreatePrivilegeTokenRequest) returns (types.UserTokenV3);
|
||||
|
||||
// GetInstaller retrieves the installer script resource
|
||||
rpc GetInstaller(google.protobuf.Empty) returns (types.InstallerV1);
|
||||
|
||||
// SetInstaller sets the installer script resource
|
||||
rpc SetInstaller(types.InstallerV1) returns (google.protobuf.Empty);
|
||||
|
||||
// DeleteInstaller removes the installer script resource
|
||||
rpc DeleteInstaller(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
|
||||
// ListResources retrieves a paginated list of resources.
|
||||
rpc ListResources(ListResourcesRequest) returns (ListResourcesResponse);
|
||||
|
||||
|
|
|
@ -185,6 +185,10 @@ const (
|
|||
// cluster networking configuration.
|
||||
MetaNameClusterNetworkingConfig = "cluster-networking-config"
|
||||
|
||||
// MetaNameClusterInstallerScript is the exact name of the
|
||||
// singleton resource holding an installer script
|
||||
MetaNameClusterInstallerScript = "cluster-install-script"
|
||||
|
||||
// KindSemaphore is the resource that provides distributed semaphore functionality
|
||||
KindSemaphore = "semaphore"
|
||||
|
||||
|
@ -266,6 +270,10 @@ const (
|
|||
// KindDatabaseCertificate is a resource to control Database Certificates generation
|
||||
KindDatabaseCertificate = "database_certificate"
|
||||
|
||||
// KindInstaller is a resource that holds a node installer script
|
||||
// used to install teleport on discovered nodes
|
||||
KindInstaller = "installer"
|
||||
|
||||
// V5 is the fifth version of resources.
|
||||
V5 = "v5"
|
||||
|
||||
|
|
136
api/types/installer.go
Normal file
136
api/types/installer.go
Normal file
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* Copyright 2022 Gravitational, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
// Installer is an installer script rseource
|
||||
type Installer interface {
|
||||
Resource
|
||||
|
||||
// GetScript returns the contents of the installer script
|
||||
GetScript() string
|
||||
// SetScript sets the installer script
|
||||
SetScript(string)
|
||||
|
||||
String() string
|
||||
}
|
||||
|
||||
// NewInstallerV1 returns a new installer resource
|
||||
func NewInstallerV1(script string) (*InstallerV1, error) {
|
||||
installer := &InstallerV1{
|
||||
Metadata: Metadata{},
|
||||
Spec: InstallerSpecV1{
|
||||
Script: script,
|
||||
},
|
||||
}
|
||||
if err := installer.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return installer, nil
|
||||
}
|
||||
|
||||
// MustNewInstallerV1 creates a new installer resource from the provided script.
|
||||
//
|
||||
// Panics in case of any error when creating the resource.
|
||||
func MustNewInstallerV1(script string) *InstallerV1 {
|
||||
inst, err := NewInstallerV1(script)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults implements Installer
|
||||
func (c *InstallerV1) CheckAndSetDefaults() error {
|
||||
c.setStaticFields()
|
||||
return trace.Wrap(c.Metadata.CheckAndSetDefaults())
|
||||
}
|
||||
|
||||
// GetVersion returns resource version.
|
||||
func (c *InstallerV1) GetVersion() string {
|
||||
return c.Version
|
||||
}
|
||||
|
||||
// GetName returns the name of the resource.
|
||||
func (c *InstallerV1) GetName() string {
|
||||
return c.Metadata.Name
|
||||
}
|
||||
|
||||
// SetName sets the name of the resource.
|
||||
func (c *InstallerV1) SetName(e string) {
|
||||
c.Metadata.Name = e
|
||||
}
|
||||
|
||||
// SetExpiry sets expiry time for the object.
|
||||
func (c *InstallerV1) SetExpiry(expires time.Time) {
|
||||
c.Metadata.SetExpiry(expires)
|
||||
}
|
||||
|
||||
// Expiry returns object expiry setting.
|
||||
func (c *InstallerV1) Expiry() time.Time {
|
||||
return c.Metadata.Expiry()
|
||||
}
|
||||
|
||||
// GetMetadata returns object metadata.
|
||||
func (c *InstallerV1) GetMetadata() Metadata {
|
||||
return c.Metadata
|
||||
}
|
||||
|
||||
// GetResourceID returns resource ID.
|
||||
func (c *InstallerV1) GetResourceID() int64 {
|
||||
return c.Metadata.ID
|
||||
}
|
||||
|
||||
// SetResourceID sets resource ID.
|
||||
func (c *InstallerV1) SetResourceID(id int64) {
|
||||
c.Metadata.ID = id
|
||||
}
|
||||
|
||||
// GetKind returns resource kind.
|
||||
func (c *InstallerV1) GetKind() string {
|
||||
return c.Kind
|
||||
}
|
||||
|
||||
// GetSubKind returns resource subkind.
|
||||
func (c *InstallerV1) GetSubKind() string {
|
||||
return c.SubKind
|
||||
}
|
||||
|
||||
// SetSubKind sets resource subkind.
|
||||
func (c *InstallerV1) SetSubKind(sk string) {
|
||||
c.SubKind = sk
|
||||
}
|
||||
|
||||
func (c *InstallerV1) GetScript() string {
|
||||
return c.Spec.Script
|
||||
}
|
||||
|
||||
func (c *InstallerV1) SetScript(s string) {
|
||||
c.Spec.Script = s
|
||||
}
|
||||
|
||||
// setStaticFields sets static resource header and metadata fields.
|
||||
func (c *InstallerV1) setStaticFields() {
|
||||
c.Kind = KindInstaller
|
||||
c.Version = V1
|
||||
c.Metadata.Name = MetaNameClusterInstallerScript
|
||||
}
|
45
api/types/installers/installer.sh.tmpl
Normal file
45
api/types/installers/installer.sh.tmpl
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh
|
||||
(
|
||||
flock -n 9 || exit 1
|
||||
if test -f /usr/local/bin/teleport; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
distro_id="$(awk -F= '$1 == "ID" { print tolower($2) }' /etc/os-release | xargs echo)"
|
||||
if [ "$distro_id" = "debian" ] || [ "$distro_id" = "ubuntu" ]; then
|
||||
sudo curl https://deb.releases.teleport.dev/teleport-pubkey.asc \
|
||||
-o /usr/share/keyrings/teleport-archive-keyring.asc
|
||||
. /etc/os-release
|
||||
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} stable/{{ .MajorVersion }}" |
|
||||
sudo tee /etc/apt/sources.list.d/teleport.list >/dev/null
|
||||
sudo apt-get update
|
||||
sudo apt-get install teleport jq
|
||||
elif [ "$distro_id" = "amzn" ] || [ "$distro_id" = "rhel" ]; then
|
||||
. /etc/os-release
|
||||
sudo yum-config-manager --add-repo \
|
||||
"$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/stable/{{ .MajorVersion }}/teleport.repo")"
|
||||
sudo yum install -y teleport jq
|
||||
else
|
||||
echo "Unsupported distro: $distro_id"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTANCE_INFO="$(curl http://169.254.169.254/latest/dynamic/instance-identity/document)"
|
||||
|
||||
ACCOUNT_ID="$(echo "$INSTANCE_INFO" | jq -r .accountId)"
|
||||
INSTANCE_ID="$(echo "$INSTANCE_INFO" | jq -r .instanceId)"
|
||||
|
||||
# generate teleport ssh config
|
||||
# token is read as a parameter from the AWS ssm script run and
|
||||
# passed as the first argument to the script
|
||||
sudo /usr/local/bin/teleport node configure \
|
||||
--auth-server="{{ .PublicProxyAddr }}" \
|
||||
--join-method=iam \
|
||||
--token="$1" \
|
||||
--output=file \
|
||||
--labels="teleport.dev/instance-id=${INSTANCE_ID},teleport.dev/account-id=${ACCOUNT_ID}"
|
||||
|
||||
# enable and start teleport service
|
||||
sudo systemctl enable --now teleport
|
||||
|
||||
) 9>/var/lock/teleport_install.lock
|
39
api/types/installers/installers.go
Normal file
39
api/types/installers/installers.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package installers
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
)
|
||||
|
||||
//go:embed installer.sh.tmpl
|
||||
var defaultInstallScript string
|
||||
|
||||
// DefaultInstaller represents a the default installer script provided
|
||||
// by teleport
|
||||
var DefaultInstaller = types.MustNewInstallerV1(defaultInstallScript)
|
||||
|
||||
// Template is used to fill proxy address and version information into
|
||||
// the installer script
|
||||
type Template struct {
|
||||
// PublicProxyAddr is public address of the proxy
|
||||
PublicProxyAddr string
|
||||
// MajorVersion is the major version of the Teleport auth node
|
||||
MajorVersion string
|
||||
}
|
|
@ -10022,6 +10022,99 @@ func (m *Participant) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_Participant proto.InternalMessageInfo
|
||||
|
||||
// InstallerV1 represents an installer script resource. Used to
|
||||
// provide a script to install teleport on discovered nodes.
|
||||
type InstallerV1 struct {
|
||||
// Kind is the resource kind.
|
||||
Kind string `protobuf:"bytes,1,opt,name=Kind,proto3" json:"kind"`
|
||||
// SubKind is an optional resource subkind. Currently unused for this resource.
|
||||
SubKind string `protobuf:"bytes,2,opt,name=SubKind,proto3" json:"sub_kind,omitempty"`
|
||||
// Version is the resource version.
|
||||
Version string `protobuf:"bytes,3,opt,name=Version,proto3" json:"version"`
|
||||
// Metadata is the resource metadata.
|
||||
Metadata Metadata `protobuf:"bytes,4,opt,name=Metadata,proto3" json:"metadata"`
|
||||
// Spec is the resource spec.
|
||||
Spec InstallerSpecV1 `protobuf:"bytes,5,opt,name=Spec,proto3" json:"spec"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *InstallerV1) Reset() { *m = InstallerV1{} }
|
||||
func (m *InstallerV1) String() string { return proto.CompactTextString(m) }
|
||||
func (*InstallerV1) ProtoMessage() {}
|
||||
func (*InstallerV1) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d938547f84707355, []int{188}
|
||||
}
|
||||
func (m *InstallerV1) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *InstallerV1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_InstallerV1.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *InstallerV1) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_InstallerV1.Merge(m, src)
|
||||
}
|
||||
func (m *InstallerV1) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *InstallerV1) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_InstallerV1.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_InstallerV1 proto.InternalMessageInfo
|
||||
|
||||
// InstallerSpecV1 is the specification for an Installer
|
||||
type InstallerSpecV1 struct {
|
||||
// Script represents the contents of a installer shell script
|
||||
Script string `protobuf:"bytes,1,opt,name=Script,proto3" json:"script"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *InstallerSpecV1) Reset() { *m = InstallerSpecV1{} }
|
||||
func (m *InstallerSpecV1) String() string { return proto.CompactTextString(m) }
|
||||
func (*InstallerSpecV1) ProtoMessage() {}
|
||||
func (*InstallerSpecV1) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d938547f84707355, []int{189}
|
||||
}
|
||||
func (m *InstallerSpecV1) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *InstallerSpecV1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_InstallerSpecV1.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *InstallerSpecV1) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_InstallerSpecV1.Merge(m, src)
|
||||
}
|
||||
func (m *InstallerSpecV1) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *InstallerSpecV1) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_InstallerSpecV1.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_InstallerSpecV1 proto.InternalMessageInfo
|
||||
|
||||
// SortBy defines a sort criteria.
|
||||
type SortBy struct {
|
||||
// IsDesc is a sort direction flag where if true the direction is descending, else ascending.
|
||||
|
@ -10037,7 +10130,7 @@ func (m *SortBy) Reset() { *m = SortBy{} }
|
|||
func (m *SortBy) String() string { return proto.CompactTextString(m) }
|
||||
func (*SortBy) ProtoMessage() {}
|
||||
func (*SortBy) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d938547f84707355, []int{188}
|
||||
return fileDescriptor_d938547f84707355, []int{190}
|
||||
}
|
||||
func (m *SortBy) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -10084,7 +10177,7 @@ func (m *ConnectionDiagnosticV1) Reset() { *m = ConnectionDiagnosticV1{}
|
|||
func (m *ConnectionDiagnosticV1) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConnectionDiagnosticV1) ProtoMessage() {}
|
||||
func (*ConnectionDiagnosticV1) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d938547f84707355, []int{189}
|
||||
return fileDescriptor_d938547f84707355, []int{191}
|
||||
}
|
||||
func (m *ConnectionDiagnosticV1) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -10125,7 +10218,7 @@ func (m *ConnectionDiagnosticSpecV1) Reset() { *m = ConnectionDiagnostic
|
|||
func (m *ConnectionDiagnosticSpecV1) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConnectionDiagnosticSpecV1) ProtoMessage() {}
|
||||
func (*ConnectionDiagnosticSpecV1) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d938547f84707355, []int{190}
|
||||
return fileDescriptor_d938547f84707355, []int{192}
|
||||
}
|
||||
func (m *ConnectionDiagnosticSpecV1) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -10370,6 +10463,8 @@ func init() {
|
|||
proto.RegisterType((*SessionTrackerSpecV1)(nil), "types.SessionTrackerSpecV1")
|
||||
proto.RegisterType((*SessionTrackerPolicySet)(nil), "types.SessionTrackerPolicySet")
|
||||
proto.RegisterType((*Participant)(nil), "types.Participant")
|
||||
proto.RegisterType((*InstallerV1)(nil), "types.InstallerV1")
|
||||
proto.RegisterType((*InstallerSpecV1)(nil), "types.InstallerSpecV1")
|
||||
proto.RegisterType((*SortBy)(nil), "types.SortBy")
|
||||
proto.RegisterType((*ConnectionDiagnosticV1)(nil), "types.ConnectionDiagnosticV1")
|
||||
proto.RegisterType((*ConnectionDiagnosticSpecV1)(nil), "types.ConnectionDiagnosticSpecV1")
|
||||
|
@ -10378,7 +10473,7 @@ func init() {
|
|||
func init() { proto.RegisterFile("types.proto", fileDescriptor_d938547f84707355) }
|
||||
|
||||
var fileDescriptor_d938547f84707355 = []byte{
|
||||
// 14224 bytes of a gzipped FileDescriptorProto
|
||||
// 14263 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x7d, 0x6c, 0x1c, 0x49,
|
||||
0x76, 0x18, 0xae, 0x9e, 0x19, 0x92, 0xc3, 0xc7, 0x21, 0x39, 0x2c, 0x52, 0x12, 0xa5, 0xd5, 0x2e,
|
||||
0xb5, 0xbd, 0xbb, 0x5a, 0xad, 0x76, 0x57, 0x3a, 0x51, 0xb7, 0x3a, 0xef, 0xed, 0xd7, 0xcd, 0x90,
|
||||
|
@ -11237,37 +11332,40 @@ var fileDescriptor_d938547f84707355 = []byte{
|
|||
0x8d, 0x2f, 0xf3, 0xf4, 0x4b, 0x0a, 0x87, 0x1c, 0x57, 0xe7, 0x28, 0x99, 0xb9, 0xe3, 0x5d, 0x20,
|
||||
0xf8, 0x98, 0x60, 0x3e, 0xc1, 0x6b, 0xa6, 0xfc, 0x15, 0xf8, 0x78, 0xe0, 0x17, 0x01, 0x56, 0x9c,
|
||||
0x30, 0xaa, 0xd4, 0x23, 0xef, 0x3e, 0x1d, 0x40, 0x73, 0x27, 0x09, 0xcc, 0x1d, 0x7c, 0x04, 0x96,
|
||||
0x91, 0x75, 0x25, 0x30, 0x8f, 0x19, 0x9a, 0xab, 0x30, 0x5c, 0xf3, 0x83, 0xa8, 0x7a, 0xc0, 0x97,
|
||||
0xe3, 0x45, 0x1a, 0xd6, 0x55, 0x4f, 0xa6, 0x87, 0x3e, 0x8d, 0xba, 0x25, 0x8a, 0x98, 0x4d, 0x7c,
|
||||
0xcb, 0xa3, 0x0d, 0x57, 0x8d, 0x30, 0xd9, 0x61, 0x00, 0x8b, 0xc3, 0x99, 0xc9, 0x72, 0x26, 0xc9,
|
||||
0x70, 0x94, 0x84, 0xb2, 0x3c, 0xea, 0xaa, 0xbd, 0xa0, 0x19, 0x52, 0xcf, 0xea, 0x19, 0xc6, 0xb5,
|
||||
0x9a, 0xfa, 0xac, 0xdd, 0x1f, 0xc0, 0xf9, 0xde, 0x14, 0x6a, 0x70, 0x8c, 0xd1, 0x27, 0x38, 0xe6,
|
||||
0x85, 0xb4, 0xe3, 0x0d, 0xd1, 0x84, 0xe3, 0x2d, 0x76, 0xb7, 0x5d, 0x79, 0x07, 0x26, 0xe5, 0x0c,
|
||||
0xdf, 0x58, 0xa9, 0xe1, 0xa7, 0x9c, 0x84, 0xb1, 0x7b, 0x4b, 0xd6, 0xf2, 0xad, 0xcf, 0xd9, 0xb7,
|
||||
0x36, 0x57, 0x56, 0xca, 0xa7, 0xc8, 0x38, 0x8c, 0x0a, 0xc0, 0x42, 0xa5, 0x6c, 0x90, 0x12, 0x14,
|
||||
0x97, 0x57, 0x6b, 0x4b, 0x0b, 0x9b, 0xd6, 0x52, 0x39, 0x77, 0xe5, 0x05, 0x98, 0x48, 0x82, 0xae,
|
||||
0xf1, 0x84, 0x6b, 0x04, 0xf2, 0x56, 0x65, 0xab, 0x7c, 0x8a, 0x00, 0x0c, 0xaf, 0xdf, 0x59, 0xa8,
|
||||
0x5d, 0xbf, 0x5e, 0x36, 0xae, 0x7c, 0x02, 0xa6, 0x70, 0xd7, 0xba, 0xc2, 0x36, 0x50, 0x2d, 0x1a,
|
||||
0x60, 0x4d, 0x25, 0x28, 0xd6, 0x68, 0xdb, 0x09, 0x9c, 0x88, 0xf2, 0x6a, 0xee, 0x76, 0x1a, 0x91,
|
||||
0xd7, 0x6e, 0xd0, 0x87, 0x65, 0xe3, 0xca, 0xeb, 0x30, 0x69, 0xf9, 0x9d, 0xc8, 0x6b, 0xed, 0xca,
|
||||
0x77, 0x80, 0xc9, 0x69, 0x98, 0xda, 0x5c, 0xad, 0xdc, 0xad, 0x2e, 0xbf, 0xbb, 0xb9, 0xb6, 0x59,
|
||||
0xb3, 0xef, 0x56, 0x36, 0x16, 0x6e, 0x97, 0x4f, 0xb1, 0x06, 0xdf, 0x5d, 0xab, 0x6d, 0xd8, 0xd6,
|
||||
0xd2, 0xc2, 0xd2, 0xea, 0x46, 0xd9, 0xb8, 0xf2, 0x33, 0x06, 0x4c, 0x30, 0xe9, 0xc5, 0xfd, 0xcf,
|
||||
0x26, 0xba, 0x15, 0x2f, 0xc2, 0x85, 0xcd, 0xda, 0x92, 0x65, 0x6f, 0xac, 0xdd, 0x59, 0x5a, 0xb5,
|
||||
0x37, 0x6b, 0x95, 0x77, 0x97, 0xec, 0xcd, 0xd5, 0xda, 0xfa, 0xd2, 0xc2, 0xf2, 0xad, 0xe5, 0xa5,
|
||||
0xc5, 0xf2, 0x29, 0x32, 0x07, 0x4f, 0x29, 0x18, 0xd6, 0xd2, 0xc2, 0xda, 0xbd, 0x25, 0xcb, 0x5e,
|
||||
0xaf, 0xd4, 0x6a, 0x5b, 0x6b, 0xd6, 0x62, 0xd9, 0x20, 0xe7, 0xe1, 0x4c, 0x06, 0xc2, 0xdd, 0x5b,
|
||||
0x95, 0x72, 0xae, 0xab, 0x6c, 0x75, 0x69, 0xab, 0xb2, 0x62, 0x57, 0xd7, 0x36, 0xca, 0xf9, 0x2b,
|
||||
0xef, 0x30, 0x0b, 0x54, 0x3c, 0x68, 0xcc, 0x2c, 0x9c, 0x22, 0x14, 0x56, 0xd7, 0x56, 0x97, 0xca,
|
||||
0xa7, 0xc8, 0x18, 0x8c, 0xac, 0x2f, 0xad, 0x2e, 0x2e, 0xaf, 0xbe, 0xcb, 0x87, 0xb5, 0xb2, 0xbe,
|
||||
0x6e, 0xad, 0xdd, 0x5b, 0x5a, 0x2c, 0xe7, 0xd8, 0xd8, 0x2d, 0x2e, 0xad, 0xb2, 0x96, 0xe5, 0xaf,
|
||||
0x98, 0xfc, 0x9d, 0x6d, 0xed, 0xf5, 0x4e, 0x36, 0x5a, 0x4b, 0x9f, 0xdd, 0x58, 0x5a, 0xad, 0x2d,
|
||||
0xaf, 0xad, 0x96, 0x4f, 0x5d, 0xb9, 0x90, 0xc2, 0x91, 0x5f, 0xa2, 0x56, 0xbb, 0x5d, 0x3e, 0x75,
|
||||
0xe5, 0x0b, 0x50, 0x52, 0x0d, 0x30, 0x72, 0x16, 0xa6, 0xd5, 0xdf, 0xeb, 0xb4, 0xe5, 0x7a, 0xad,
|
||||
0xdd, 0xf2, 0xa9, 0x74, 0x81, 0xd5, 0x69, 0xb5, 0x58, 0x01, 0x76, 0x5e, 0x2d, 0xd8, 0xa0, 0x41,
|
||||
0xd3, 0x6b, 0x31, 0xdb, 0xaa, 0x9c, 0xab, 0x96, 0xbf, 0xfb, 0xc7, 0xcf, 0x9c, 0xfa, 0xee, 0xf7,
|
||||
0x9f, 0x31, 0xfe, 0xe8, 0xfb, 0xcf, 0x18, 0xff, 0xed, 0xfb, 0xcf, 0x18, 0xdb, 0xc3, 0x38, 0xe3,
|
||||
0x6f, 0xfc, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xba, 0xb9, 0x2b, 0x33, 0x1c, 0xe2, 0x00, 0x00,
|
||||
0x91, 0x75, 0x25, 0x30, 0x8f, 0x19, 0x9a, 0x7f, 0x69, 0xc0, 0xd8, 0x72, 0x2b, 0x8c, 0x9c, 0x46,
|
||||
0x03, 0x97, 0xd6, 0x8f, 0x53, 0xaa, 0xba, 0xb8, 0x5f, 0x7d, 0x96, 0xf3, 0xd7, 0x60, 0x32, 0x85,
|
||||
0xc6, 0xb6, 0x1c, 0x35, 0xbc, 0x8e, 0xa2, 0x6e, 0x39, 0xf8, 0x05, 0x15, 0x4b, 0x94, 0x98, 0xab,
|
||||
0x30, 0x5c, 0xf3, 0x83, 0xa8, 0x7a, 0xc0, 0xad, 0x98, 0x45, 0x1a, 0xd6, 0x55, 0x07, 0xb0, 0x87,
|
||||
0xae, 0xa0, 0xba, 0x25, 0x8a, 0xd8, 0x56, 0xe2, 0x96, 0x47, 0x1b, 0xae, 0x1a, 0x98, 0xb3, 0xc3,
|
||||
0x00, 0x16, 0x87, 0x33, 0x4b, 0xef, 0x4c, 0x92, 0x18, 0x2a, 0x89, 0x00, 0x7a, 0x54, 0x63, 0x67,
|
||||
0x41, 0x1b, 0x98, 0x67, 0xf5, 0xc4, 0xec, 0x5a, 0x4d, 0x7d, 0xc6, 0xe8, 0x03, 0x38, 0xdf, 0x9b,
|
||||
0x42, 0x8d, 0x29, 0x32, 0xfa, 0xc4, 0x14, 0xbd, 0x90, 0xf6, 0x57, 0x22, 0x9a, 0xf0, 0x57, 0xc6,
|
||||
0x5e, 0xca, 0x2b, 0xef, 0xc0, 0xa4, 0x54, 0x8c, 0x1b, 0x2b, 0x35, 0x9c, 0x01, 0x93, 0x30, 0x76,
|
||||
0x6f, 0xc9, 0x5a, 0xbe, 0xf5, 0x39, 0xfb, 0xd6, 0xe6, 0xca, 0x4a, 0xf9, 0x14, 0x19, 0x87, 0x51,
|
||||
0x01, 0x58, 0xa8, 0x94, 0x0d, 0x52, 0x82, 0xe2, 0xf2, 0x6a, 0x6d, 0x69, 0x61, 0xd3, 0x5a, 0x2a,
|
||||
0xe7, 0xae, 0xbc, 0x00, 0x13, 0x49, 0xac, 0x3a, 0x1e, 0x0c, 0x8e, 0x40, 0xde, 0xaa, 0x6c, 0x95,
|
||||
0x4f, 0x11, 0x80, 0xe1, 0xf5, 0x3b, 0x0b, 0xb5, 0xeb, 0xd7, 0xcb, 0xc6, 0x95, 0x4f, 0xc0, 0x14,
|
||||
0x6e, 0xf6, 0x57, 0xd8, 0xbe, 0xb3, 0x45, 0x03, 0xac, 0xa9, 0x04, 0xc5, 0x1a, 0x6d, 0x3b, 0x81,
|
||||
0x13, 0x51, 0x5e, 0xcd, 0xdd, 0x4e, 0x23, 0xf2, 0xda, 0x0d, 0xfa, 0xb0, 0x6c, 0x5c, 0x79, 0x1d,
|
||||
0x26, 0x2d, 0xbf, 0x13, 0x79, 0xad, 0x5d, 0xf9, 0x7c, 0x32, 0x39, 0x0d, 0x53, 0x9b, 0xab, 0x95,
|
||||
0xbb, 0xd5, 0xe5, 0x77, 0x37, 0xd7, 0x36, 0x6b, 0xf6, 0xdd, 0xca, 0xc6, 0xc2, 0xed, 0xf2, 0x29,
|
||||
0xd6, 0xe0, 0xbb, 0x6b, 0xb5, 0x0d, 0xdb, 0x5a, 0x5a, 0x58, 0x5a, 0xdd, 0x28, 0x1b, 0x57, 0x7e,
|
||||
0xc6, 0x80, 0x09, 0x36, 0xe9, 0x71, 0xdb, 0xb8, 0x89, 0xde, 0xd8, 0x8b, 0x70, 0x61, 0xb3, 0xb6,
|
||||
0x64, 0xd9, 0x1b, 0x6b, 0x77, 0x96, 0x56, 0xed, 0xcd, 0x5a, 0xe5, 0xdd, 0x25, 0x7b, 0x73, 0xb5,
|
||||
0xb6, 0xbe, 0xb4, 0xb0, 0x7c, 0x6b, 0x79, 0x69, 0xb1, 0x7c, 0x8a, 0xcc, 0xc1, 0x53, 0x0a, 0x86,
|
||||
0xb5, 0xb4, 0xb0, 0x76, 0x6f, 0xc9, 0xb2, 0xd7, 0x2b, 0xb5, 0xda, 0xd6, 0x9a, 0xb5, 0x58, 0x36,
|
||||
0xc8, 0x79, 0x38, 0x93, 0x81, 0x70, 0xf7, 0x56, 0xa5, 0x9c, 0xeb, 0x2a, 0x5b, 0x5d, 0xda, 0xaa,
|
||||
0xac, 0xd8, 0xd5, 0xb5, 0x8d, 0x72, 0xfe, 0xca, 0x3b, 0xcc, 0x70, 0x17, 0xef, 0x40, 0x33, 0xc3,
|
||||
0xb0, 0x08, 0x85, 0xd5, 0xb5, 0xd5, 0xa5, 0xf2, 0x29, 0x32, 0x06, 0x23, 0xeb, 0x4b, 0xab, 0x8b,
|
||||
0xcb, 0xab, 0xef, 0xf2, 0x61, 0xad, 0xac, 0xaf, 0x5b, 0x6b, 0xf7, 0x96, 0x16, 0xcb, 0x39, 0x36,
|
||||
0x76, 0x8b, 0x4b, 0xab, 0xac, 0x65, 0xf9, 0x2b, 0x26, 0x7f, 0x9e, 0x5c, 0x7b, 0xf4, 0x94, 0x8d,
|
||||
0xd6, 0xd2, 0x67, 0x37, 0x96, 0x56, 0x6b, 0xcb, 0x6b, 0xab, 0xe5, 0x53, 0x57, 0x2e, 0xa4, 0x70,
|
||||
0xe4, 0x97, 0xa8, 0xd5, 0x6e, 0x97, 0x4f, 0x5d, 0xf9, 0x02, 0x94, 0x54, 0xbb, 0x95, 0x9c, 0x85,
|
||||
0x69, 0xf5, 0xf7, 0x3a, 0x6d, 0xb9, 0x5e, 0x6b, 0xb7, 0x7c, 0x2a, 0x5d, 0x60, 0x75, 0x5a, 0x2d,
|
||||
0x56, 0x80, 0x9d, 0x57, 0x0b, 0x36, 0x68, 0xd0, 0xf4, 0x5a, 0xcc, 0x24, 0x2d, 0xe7, 0xaa, 0xe5,
|
||||
0xef, 0xfe, 0xf1, 0x33, 0xa7, 0xbe, 0xfb, 0xfd, 0x67, 0x8c, 0x3f, 0xfa, 0xfe, 0x33, 0xc6, 0x7f,
|
||||
0xfb, 0xfe, 0x33, 0xc6, 0xf6, 0x30, 0x2a, 0xca, 0x1b, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0x52,
|
||||
0xdd, 0xc5, 0xcf, 0x53, 0xe3, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *KeepAlive) Marshal() (dAtA []byte, err error) {
|
||||
|
@ -23851,6 +23949,108 @@ func (m *Participant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *InstallerV1) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *InstallerV1) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *InstallerV1) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
{
|
||||
size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintTypes(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
{
|
||||
size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintTypes(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
if len(m.Version) > 0 {
|
||||
i -= len(m.Version)
|
||||
copy(dAtA[i:], m.Version)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.Version)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.SubKind) > 0 {
|
||||
i -= len(m.SubKind)
|
||||
copy(dAtA[i:], m.SubKind)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.SubKind)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Kind) > 0 {
|
||||
i -= len(m.Kind)
|
||||
copy(dAtA[i:], m.Kind)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.Kind)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *InstallerSpecV1) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *InstallerSpecV1) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *InstallerSpecV1) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.Script) > 0 {
|
||||
i -= len(m.Script)
|
||||
copy(dAtA[i:], m.Script)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.Script)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *SortBy) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
|
@ -29637,6 +29837,50 @@ func (m *Participant) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *InstallerV1) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Kind)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = len(m.SubKind)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = len(m.Version)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = m.Metadata.Size()
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
l = m.Spec.Size()
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *InstallerSpecV1) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Script)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *SortBy) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
|
@ -67582,6 +67826,302 @@ func (m *Participant) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *InstallerV1) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: InstallerV1: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: InstallerV1: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Kind = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SubKind", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SubKind = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Version = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTypes(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *InstallerSpecV1) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: InstallerSpecV1: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: InstallerSpecV1: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Script", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Script = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTypes(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *SortBy) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
|
@ -3587,6 +3587,27 @@ message Participant {
|
|||
];
|
||||
}
|
||||
|
||||
// InstallerV1 represents an installer script resource. Used to
|
||||
// provide a script to install teleport on discovered nodes.
|
||||
message InstallerV1 {
|
||||
// Kind is the resource kind.
|
||||
string Kind = 1 [ (gogoproto.jsontag) = "kind" ];
|
||||
// SubKind is an optional resource subkind. Currently unused for this resource.
|
||||
string SubKind = 2 [ (gogoproto.jsontag) = "sub_kind,omitempty" ];
|
||||
// Version is the resource version.
|
||||
string Version = 3 [ (gogoproto.jsontag) = "version" ];
|
||||
// Metadata is the resource metadata.
|
||||
Metadata Metadata = 4 [ (gogoproto.nullable) = false, (gogoproto.jsontag) = "metadata" ];
|
||||
// Spec is the resource spec.
|
||||
InstallerSpecV1 Spec = 5 [ (gogoproto.nullable) = false, (gogoproto.jsontag) = "spec" ];
|
||||
}
|
||||
|
||||
// InstallerSpecV1 is the specification for an Installer
|
||||
message InstallerSpecV1 {
|
||||
// Script represents the contents of a installer shell script
|
||||
string Script = 1 [ (gogoproto.jsontag) = "script" ];
|
||||
}
|
||||
|
||||
// SessionState represents the state of a session.
|
||||
enum SessionState {
|
||||
// Pending variant represents a session that is waiting on participants to fulfill the criteria
|
||||
|
|
|
@ -839,6 +839,9 @@ type Cache interface {
|
|||
ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error)
|
||||
// ListWindowsDesktops returns a paginated list of windows desktops.
|
||||
ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error)
|
||||
|
||||
// GetInstaller gets installer resource for this cluster
|
||||
GetInstaller(ctx context.Context) (types.Installer, error)
|
||||
}
|
||||
|
||||
type NodeWrapper struct {
|
||||
|
|
|
@ -2104,3 +2104,29 @@ func TestEnforcerGetLicenseCheckResult(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, expected, heartbeat.Spec.Notifications)
|
||||
}
|
||||
|
||||
func TestInstallerCRUD(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := newAuthSuite(t)
|
||||
ctx := context.Background()
|
||||
|
||||
var inst types.Installer
|
||||
var err error
|
||||
contents := "#! just some script contents"
|
||||
inst, err = types.NewInstallerV1(contents)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.a.SetInstaller(ctx, inst))
|
||||
|
||||
inst, err = s.a.GetInstaller(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, contents, inst.GetScript())
|
||||
|
||||
// resets to the default installer
|
||||
err = s.a.DeleteInstaller(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.a.GetInstaller(ctx)
|
||||
require.Error(t, err)
|
||||
require.True(t, trace.IsNotFound(err))
|
||||
}
|
||||
|
|
|
@ -3291,6 +3291,30 @@ func (a *ServerWithRoles) GetAuthPreference(ctx context.Context) (types.AuthPref
|
|||
return a.authServer.GetAuthPreference(ctx)
|
||||
}
|
||||
|
||||
// GetInstaller retrieves an installer script resource
|
||||
func (a *ServerWithRoles) GetInstaller(ctx context.Context) (types.Installer, error) {
|
||||
if err := a.action(apidefaults.Namespace, types.KindInstaller, types.VerbRead); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return a.authServer.GetInstaller(ctx)
|
||||
}
|
||||
|
||||
// SetInstaller sets an Installer script resource
|
||||
func (a *ServerWithRoles) SetInstaller(ctx context.Context, inst types.Installer) error {
|
||||
if err := a.action(apidefaults.Namespace, types.KindInstaller, types.VerbUpdate, types.VerbCreate); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
return trace.Wrap(a.authServer.SetInstaller(ctx, inst))
|
||||
}
|
||||
|
||||
// DeleteInstaller removes an installer script resource
|
||||
func (a *ServerWithRoles) DeleteInstaller(ctx context.Context) error {
|
||||
if err := a.action(apidefaults.Namespace, types.KindInstaller, types.VerbDelete); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
return trace.Wrap(a.authServer.DeleteInstaller(ctx))
|
||||
}
|
||||
|
||||
// SetAuthPreference sets cluster auth preference.
|
||||
func (a *ServerWithRoles) SetAuthPreference(ctx context.Context, newAuthPref types.AuthPreference) error {
|
||||
storedAuthPref, err := a.authServer.GetAuthPreference(ctx)
|
||||
|
|
|
@ -324,6 +324,98 @@ func TestSAMLAuthRequest(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestInstaller(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
srv := newTestTLSServer(t)
|
||||
|
||||
_, err := CreateRole(ctx, srv.Auth(), "test-empty", types.RoleSpecV5{})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = CreateRole(ctx, srv.Auth(), "test-read", types.RoleSpecV5{
|
||||
Allow: types.RoleConditions{
|
||||
Rules: []types.Rule{
|
||||
{
|
||||
Resources: []string{types.KindInstaller},
|
||||
Verbs: []string{types.VerbRead},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = CreateRole(ctx, srv.Auth(), "test-update", types.RoleSpecV5{
|
||||
Allow: types.RoleConditions{
|
||||
Rules: []types.Rule{
|
||||
{
|
||||
Resources: []string{types.KindInstaller},
|
||||
Verbs: []string{types.VerbUpdate, types.VerbCreate},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = CreateRole(ctx, srv.Auth(), "test-delete", types.RoleSpecV5{
|
||||
Allow: types.RoleConditions{
|
||||
Rules: []types.Rule{
|
||||
{
|
||||
Resources: []string{types.KindInstaller},
|
||||
Verbs: []string{types.VerbDelete},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
user, err := CreateUser(srv.Auth(), "testuser")
|
||||
require.NoError(t, err)
|
||||
|
||||
inst, err := types.NewInstallerV1("contents")
|
||||
require.NoError(t, err)
|
||||
err = srv.Auth().SetInstaller(ctx, inst)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tc := range []struct {
|
||||
roles []string
|
||||
assert require.ErrorAssertionFunc
|
||||
installerAction func(*Client) error
|
||||
}{{
|
||||
roles: []string{"test-empty"},
|
||||
assert: require.Error,
|
||||
installerAction: func(c *Client) error {
|
||||
_, err := c.GetInstaller(ctx)
|
||||
return err
|
||||
},
|
||||
}, {
|
||||
roles: []string{"test-read"},
|
||||
assert: require.NoError,
|
||||
installerAction: func(c *Client) error {
|
||||
_, err := c.GetInstaller(ctx)
|
||||
return err
|
||||
},
|
||||
}, {
|
||||
roles: []string{"test-update"},
|
||||
assert: require.NoError,
|
||||
installerAction: func(c *Client) error {
|
||||
inst, err := types.NewInstallerV1("new-contents")
|
||||
require.NoError(t, err)
|
||||
return c.SetInstaller(ctx, inst)
|
||||
},
|
||||
}, {
|
||||
roles: []string{"test-delete"},
|
||||
assert: require.NoError,
|
||||
installerAction: func(c *Client) error {
|
||||
err := c.DeleteInstaller(ctx)
|
||||
return err
|
||||
},
|
||||
}} {
|
||||
user.SetRoles(tc.roles)
|
||||
err = srv.Auth().UpsertUser(user)
|
||||
require.NoError(t, err)
|
||||
|
||||
client, err := srv.NewClient(TestUser(user.GetName()))
|
||||
require.NoError(t, err)
|
||||
tc.assert(t, tc.installerAction(client))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDCAuthRequest(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
srv := newTestTLSServer(t)
|
||||
|
|
|
@ -46,6 +46,7 @@ import (
|
|||
"github.com/gravitational/teleport/api/metadata"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
apievents "github.com/gravitational/teleport/api/types/events"
|
||||
"github.com/gravitational/teleport/api/types/installers"
|
||||
wanlib "github.com/gravitational/teleport/lib/auth/webauthn"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/httplib"
|
||||
|
@ -4198,7 +4199,50 @@ func (g *GRPCServer) CreateConnectionDiagnostic(ctx context.Context, connectionD
|
|||
if err := auth.ServerWithRoles.CreateConnectionDiagnostic(ctx, connectionDiagnostic); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
|
||||
// SetInstaller sets the installer script resource
|
||||
func (g *GRPCServer) SetInstaller(ctx context.Context, req *types.InstallerV1) (*empty.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err := auth.SetInstaller(ctx, req); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
|
||||
// GetInstaller retrieves the installer script resource
|
||||
func (g *GRPCServer) GetInstaller(ctx context.Context, _ *empty.Empty) (*types.InstallerV1, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
res, err := auth.GetInstaller(ctx)
|
||||
if err != nil {
|
||||
if trace.IsNotFound(err) {
|
||||
return installers.DefaultInstaller, nil
|
||||
}
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
inst, ok := res.(*types.InstallerV1)
|
||||
if !ok {
|
||||
return nil, trace.BadParameter("unexpected installer type %T", res)
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// DeleteInstaller sets the installer script resource to its default
|
||||
func (g *GRPCServer) DeleteInstaller(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
|
||||
auth, err := g.authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err := auth.DeleteInstaller(ctx); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,7 @@ func (a *authorizer) authorizeRemoteBuiltinRole(r RemoteBuiltinRole) (*Context,
|
|||
types.NewRule(types.KindClusterAuthPreference, services.RO()),
|
||||
types.NewRule(types.KindKubeService, services.RO()),
|
||||
types.NewRule(types.KindKubeServer, services.RO()),
|
||||
types.NewRule(types.KindInstaller, services.RO()),
|
||||
// this rule allows remote proxy to update the cluster's certificate authorities
|
||||
// during certificates renewal
|
||||
{
|
||||
|
@ -416,6 +417,7 @@ func roleSpecForProxy(clusterName string) types.RoleSpecV5 {
|
|||
types.NewRule(types.KindWindowsDesktopService, services.RO()),
|
||||
types.NewRule(types.KindDatabaseCertificate, []string{types.VerbCreate}),
|
||||
types.NewRule(types.KindWindowsDesktop, services.RO()),
|
||||
types.NewRule(types.KindInstaller, services.RO()),
|
||||
// this rule allows local proxy to update the remote cluster's host certificate authorities
|
||||
// during certificates renewal
|
||||
{
|
||||
|
|
18
lib/cache/cache.go
vendored
18
lib/cache/cache.go
vendored
|
@ -104,6 +104,7 @@ func ForAuth(cfg Config) Config {
|
|||
{Kind: types.KindWindowsDesktopService},
|
||||
{Kind: types.KindWindowsDesktop},
|
||||
{Kind: types.KindKubeServer},
|
||||
{Kind: types.KindInstaller},
|
||||
}
|
||||
cfg.QueueSize = defaults.AuthQueueSize
|
||||
return cfg
|
||||
|
@ -141,6 +142,7 @@ func ForProxy(cfg Config) Config {
|
|||
{Kind: types.KindWindowsDesktopService},
|
||||
{Kind: types.KindWindowsDesktop},
|
||||
{Kind: types.KindKubeServer},
|
||||
{Kind: types.KindInstaller},
|
||||
}
|
||||
cfg.QueueSize = defaults.ProxyQueueSize
|
||||
return cfg
|
||||
|
@ -172,6 +174,7 @@ func ForRemoteProxy(cfg Config) Config {
|
|||
{Kind: types.KindDatabaseServer},
|
||||
{Kind: types.KindDatabase},
|
||||
{Kind: types.KindKubeServer},
|
||||
{Kind: types.KindInstaller},
|
||||
}
|
||||
cfg.QueueSize = defaults.ProxyQueueSize
|
||||
return cfg
|
||||
|
@ -1497,6 +1500,21 @@ func (c *Cache) GetClusterName(opts ...services.MarshalOption) (types.ClusterNam
|
|||
return rg.clusterConfig.GetClusterName(opts...)
|
||||
}
|
||||
|
||||
// GetInstaller gets the installer script resource for the cluster
|
||||
func (c *Cache) GetInstaller(ctx context.Context) (types.Installer, error) {
|
||||
ctx, span := c.Tracer.Start(ctx, "cache/GetInstaller")
|
||||
defer span.End()
|
||||
|
||||
rg, err := c.read()
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
defer rg.Release()
|
||||
|
||||
inst, err := rg.clusterConfig.GetInstaller(ctx)
|
||||
return inst, trace.Wrap(err)
|
||||
}
|
||||
|
||||
// GetRoles is a part of auth.Cache implementation
|
||||
func (c *Cache) GetRoles(ctx context.Context) ([]types.Role, error) {
|
||||
ctx, span := c.Tracer.Start(ctx, "cache/GetRoles")
|
||||
|
|
1
lib/cache/cache_test.go
vendored
1
lib/cache/cache_test.go
vendored
|
@ -2607,6 +2607,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) {
|
|||
types.KindLock: &types.LockV2{},
|
||||
types.KindWindowsDesktopService: &types.WindowsDesktopServiceV3{},
|
||||
types.KindWindowsDesktop: &types.WindowsDesktopV3{},
|
||||
types.KindInstaller: &types.InstallerV1{},
|
||||
}
|
||||
|
||||
for name, cfg := range cases {
|
||||
|
|
67
lib/cache/collections.go
vendored
67
lib/cache/collections.go
vendored
|
@ -88,6 +88,11 @@ func setupCollections(c *Cache, watches []types.WatchKind) (map[resourceKind]col
|
|||
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
||||
}
|
||||
collections[resourceKind] = &sessionRecordingConfig{watch: watch, Cache: c}
|
||||
case types.KindInstaller:
|
||||
if c.ClusterConfig == nil {
|
||||
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
||||
}
|
||||
collections[resourceKind] = &installerConfig{watch: watch, Cache: c}
|
||||
case types.KindUser:
|
||||
if c.Users == nil {
|
||||
return nil, trace.BadParameter("missing parameter Users")
|
||||
|
@ -2255,6 +2260,68 @@ func (c *sessionRecordingConfig) watchKind() types.WatchKind {
|
|||
return c.watch
|
||||
}
|
||||
|
||||
type installerConfig struct {
|
||||
*Cache
|
||||
watch types.WatchKind
|
||||
}
|
||||
|
||||
func (c *installerConfig) erase(ctx context.Context) error {
|
||||
if err := c.clusterConfigCache.DeleteInstaller(ctx); err != nil {
|
||||
if !trace.IsNotFound(err) {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *installerConfig) fetch(ctx context.Context) (apply func(ctx context.Context) error, err error) {
|
||||
var noConfig bool
|
||||
resource, err := c.ClusterConfig.GetInstaller(ctx)
|
||||
if err != nil {
|
||||
if !trace.IsNotFound(err) {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
noConfig = true
|
||||
}
|
||||
return func(ctx context.Context) error {
|
||||
// either zero or one instance exists, so we either erase or
|
||||
// update, but not both.
|
||||
if noConfig {
|
||||
return trace.Wrap(c.erase(ctx))
|
||||
}
|
||||
|
||||
return trace.Wrap(c.clusterConfigCache.SetInstaller(ctx, resource))
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *installerConfig) processEvent(ctx context.Context, event types.Event) error {
|
||||
switch event.Type {
|
||||
case types.OpDelete:
|
||||
err := c.clusterConfigCache.DeleteInstaller(ctx)
|
||||
if err != nil {
|
||||
if !trace.IsNotFound(err) {
|
||||
c.Warningf("Failed to delete resource %v.", err)
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
case types.OpPut:
|
||||
resource, ok := event.Resource.(types.Installer)
|
||||
if !ok {
|
||||
return trace.BadParameter("unexpected type %T", event.Resource)
|
||||
}
|
||||
if err := c.clusterConfigCache.SetInstaller(ctx, resource); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
default:
|
||||
c.Warningf("Skipping unsupported event type %v.", event.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *installerConfig) watchKind() types.WatchKind {
|
||||
return c.watch
|
||||
}
|
||||
|
||||
type networkRestrictions struct {
|
||||
*Cache
|
||||
watch types.WatchKind
|
||||
|
|
|
@ -98,3 +98,9 @@ func SetWebConfigHeaders(h http.Header) {
|
|||
SetStaticFileHeaders(h)
|
||||
h.Set("Content-Type", "application/javascript")
|
||||
}
|
||||
|
||||
// SetScriptHeaders sets headers for the teleport install script
|
||||
func SetScriptHeaders(h http.Header) {
|
||||
SetStaticFileHeaders(h)
|
||||
h.Set("Content-Type", "text/x-shellscript")
|
||||
}
|
||||
|
|
|
@ -3391,6 +3391,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
|
|||
StaticFS: fs,
|
||||
ClusterFeatures: process.getClusterFeatures(),
|
||||
ProxySettings: proxySettings,
|
||||
PublicProxyAddr: process.proxyPublicAddr().Addr,
|
||||
})
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
|
|
|
@ -70,4 +70,11 @@ type ClusterConfiguration interface {
|
|||
SetClusterNetworkingConfig(context.Context, types.ClusterNetworkingConfig) error
|
||||
// DeleteClusterNetworkingConfig deletes ClusterNetworkingConfig from the backend.
|
||||
DeleteClusterNetworkingConfig(ctx context.Context) error
|
||||
|
||||
// GetInstaller gets the installer script from the backend
|
||||
GetInstaller(context.Context) (types.Installer, error)
|
||||
// SetInstaller sets the installer script in the backend
|
||||
SetInstaller(context.Context, types.Installer) error
|
||||
// DeleteInstaller removes the installer script from the backend
|
||||
DeleteInstaller(context.Context) error
|
||||
}
|
||||
|
|
77
lib/services/installer.go
Normal file
77
lib/services/installer.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Copyright 2022 Gravitational, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
// UnmarshalInstaller unmarshals the installer resource from JSON.
|
||||
func UnmarshalInstaller(data []byte, opts ...MarshalOption) (types.Installer, error) {
|
||||
var installer types.InstallerV1
|
||||
|
||||
if len(data) == 0 {
|
||||
return nil, trace.BadParameter("missing resource data")
|
||||
}
|
||||
|
||||
cfg, err := CollectOptions(opts)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := utils.FastUnmarshal(data, &installer); err != nil {
|
||||
return nil, trace.BadParameter(err.Error())
|
||||
}
|
||||
if err := installer.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if cfg.ID != 0 {
|
||||
installer.SetResourceID(cfg.ID)
|
||||
}
|
||||
if !cfg.Expires.IsZero() {
|
||||
installer.SetExpiry(cfg.Expires)
|
||||
}
|
||||
return &installer, nil
|
||||
}
|
||||
|
||||
// MarshalInstaller marshals the Installer resource to JSON.
|
||||
func MarshalInstaller(installer types.Installer, opts ...MarshalOption) ([]byte, error) {
|
||||
if err := installer.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
cfg, err := CollectOptions(opts)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
switch installer := installer.(type) {
|
||||
case *types.InstallerV1:
|
||||
if !cfg.PreserveResourceID {
|
||||
// avoid modifying the original object
|
||||
// to prevent unexpected data races
|
||||
copy := *installer
|
||||
copy.SetResourceID(0)
|
||||
installer = ©
|
||||
}
|
||||
return utils.FastMarshal(installer)
|
||||
default:
|
||||
return nil, trace.BadParameter("unrecognized installer version %T", installer)
|
||||
}
|
||||
}
|
|
@ -361,6 +361,36 @@ func (s *ClusterConfigurationService) DeleteSessionRecordingConfig(ctx context.C
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetInstaller gets the script of the cluster from the backend.
|
||||
func (s *ClusterConfigurationService) GetInstaller(ctx context.Context) (types.Installer, error) {
|
||||
item, err := s.Get(ctx, backend.Key(clusterConfigPrefix, installerScriptPrefix))
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return services.UnmarshalInstaller(item.Value)
|
||||
}
|
||||
|
||||
// SetInstaller sets the script of the cluster in the backend
|
||||
func (s *ClusterConfigurationService) SetInstaller(ctx context.Context, ins types.Installer) error {
|
||||
value, err := services.MarshalInstaller(ins)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
_, err = s.Put(ctx, backend.Item{
|
||||
Key: backend.Key(clusterConfigPrefix, installerScriptPrefix),
|
||||
Value: value,
|
||||
Expires: ins.Expiry(),
|
||||
})
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
// DeleteInstaller sets the installer script to default script in the backend.
|
||||
func (s *ClusterConfigurationService) DeleteInstaller(ctx context.Context) error {
|
||||
return trace.Wrap(
|
||||
s.Delete(ctx, backend.Key(clusterConfigPrefix, installerScriptPrefix)))
|
||||
}
|
||||
|
||||
const (
|
||||
clusterConfigPrefix = "cluster_configuration"
|
||||
namePrefix = "name"
|
||||
|
@ -371,4 +401,5 @@ const (
|
|||
auditPrefix = "audit"
|
||||
networkingPrefix = "networking"
|
||||
sessionRecordingPrefix = "session_recording"
|
||||
installerScriptPrefix = "installer_script"
|
||||
)
|
||||
|
|
|
@ -136,6 +136,8 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type
|
|||
parser = newWindowsDesktopServicesParser()
|
||||
case types.KindWindowsDesktop:
|
||||
parser = newWindowsDesktopsParser()
|
||||
case types.KindInstaller:
|
||||
parser = newInstallerParser()
|
||||
default:
|
||||
return nil, trace.BadParameter("watcher on object kind %q is not supported", kind.Kind)
|
||||
}
|
||||
|
@ -1263,6 +1265,39 @@ func (p *windowsDesktopsParser) parse(event backend.Event) (types.Resource, erro
|
|||
}
|
||||
}
|
||||
|
||||
type installerParser struct {
|
||||
baseParser
|
||||
}
|
||||
|
||||
func newInstallerParser() *installerParser {
|
||||
return &installerParser{
|
||||
baseParser: newBaseParser(backend.Key(clusterConfigPrefix, installerScriptPrefix)),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *installerParser) parse(event backend.Event) (types.Resource, error) {
|
||||
switch event.Type {
|
||||
case types.OpDelete:
|
||||
h, err := resourceHeader(event, types.KindInstaller, types.V1, 0)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
h.SetName(types.MetaNameClusterInstallerScript)
|
||||
return h, nil
|
||||
case types.OpPut:
|
||||
inst, err := services.UnmarshalInstaller(event.Item.Value,
|
||||
services.WithResourceID(event.Item.ID),
|
||||
services.WithExpires(event.Item.Expires),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return inst, nil
|
||||
default:
|
||||
return nil, trace.BadParameter("event %v is not supported", event.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func resourceHeader(event backend.Event, kind, version string, offset int) (types.Resource, error) {
|
||||
name, err := base(event.Item.Key, offset)
|
||||
if err != nil {
|
||||
|
|
|
@ -70,6 +70,7 @@ func NewPresetEditorRole() types.Role {
|
|||
types.NewRule(types.KindToken, RW()),
|
||||
types.NewRule(types.KindConnectionDiagnostic, RW()),
|
||||
types.NewRule(types.KindDatabaseCertificate, RW()),
|
||||
types.NewRule(types.KindInstaller, RW()),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -173,6 +173,8 @@ func ParseShortcut(in string) (string, error) {
|
|||
return types.KindWindowsDesktop, nil
|
||||
case types.KindToken, "tokens":
|
||||
return types.KindToken, nil
|
||||
case types.KindInstaller:
|
||||
return types.KindInstaller, nil
|
||||
}
|
||||
return "", trace.BadParameter("unsupported resource: %q - resources should be expressed as 'type/name', for example 'connector/github'", in)
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import (
|
|||
apidefaults "github.com/gravitational/teleport/api/defaults"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
apievents "github.com/gravitational/teleport/api/types/events"
|
||||
"github.com/gravitational/teleport/api/types/installers"
|
||||
apiutils "github.com/gravitational/teleport/api/utils"
|
||||
apisshutils "github.com/gravitational/teleport/api/utils/sshutils"
|
||||
"github.com/gravitational/teleport/lib/auth"
|
||||
|
@ -72,6 +73,7 @@ import (
|
|||
lemma_secret "github.com/mailgun/lemma/secret"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -190,6 +192,10 @@ type Config struct {
|
|||
|
||||
// ProxySettings allows fetching the current proxy settings.
|
||||
ProxySettings proxySettingsGetter
|
||||
|
||||
// PublicProxyAddr is used to template the public proxy address
|
||||
// into the installer script responses
|
||||
PublicProxyAddr string
|
||||
}
|
||||
|
||||
type APIHandler struct {
|
||||
|
@ -306,6 +312,10 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*APIHandler, error) {
|
|||
// Unauthenticated access to the message of the day
|
||||
h.GET("/webapi/motd", httplib.MakeHandler(h.motd))
|
||||
|
||||
// Unauthenticated access to retrieving the script used to install
|
||||
// Teleport
|
||||
h.GET("/webapi/scripts/installer", httplib.MakeHandler(h.installer))
|
||||
|
||||
// DELETE IN: 5.1.0
|
||||
//
|
||||
// Migrated this endpoint to /webapi/sessions/web below.
|
||||
|
@ -1379,6 +1389,30 @@ func (h *Handler) oidcCallback(w http.ResponseWriter, r *http.Request, p httprou
|
|||
return redirectURL.String()
|
||||
}
|
||||
|
||||
func (h *Handler) installer(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
||||
httplib.SetScriptHeaders(w.Header())
|
||||
installer, err := h.auth.proxyClient.GetInstaller(r.Context())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
ping, err := h.auth.Ping(r.Context())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
// semver parsing requires a 'v' at the beginning of the version string.
|
||||
version := semver.Major("v" + ping.ServerVersion)
|
||||
instTmpl, err := template.New("").Parse(installer.GetScript())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
tmpl := installers.Template{
|
||||
PublicProxyAddr: h.cfg.PublicProxyAddr,
|
||||
MajorVersion: version,
|
||||
}
|
||||
err = instTmpl.Execute(w, tmpl)
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
// AuthParams are used to construct redirect URL containing auth
|
||||
// information back to tsh login
|
||||
type AuthParams struct {
|
||||
|
|
|
@ -917,3 +917,20 @@ func (c *kubeServerCollection) writeJSON(w io.Writer) error {
|
|||
_, err = w.Write(data)
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
type installerCollection struct {
|
||||
installer types.Installer
|
||||
}
|
||||
|
||||
func (c *installerCollection) resources() (r []types.Resource) {
|
||||
return []types.Resource{c.installer}
|
||||
}
|
||||
|
||||
func (c *installerCollection) writeText(w io.Writer) error {
|
||||
t := asciitable.MakeTable([]string{"Script"})
|
||||
t.AddRow([]string{
|
||||
c.installer.GetScript(),
|
||||
})
|
||||
_, err := t.AsBuffer().WriteTo(w)
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *service.
|
|||
types.KindApp: rc.createApp,
|
||||
types.KindDatabase: rc.createDatabase,
|
||||
types.KindToken: rc.createToken,
|
||||
types.KindInstaller: rc.createInstaller,
|
||||
}
|
||||
rc.config = config
|
||||
|
||||
|
@ -592,12 +593,23 @@ func (rc *ResourceCommand) createToken(ctx context.Context, client auth.ClientI,
|
|||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
func (rc *ResourceCommand) createInstaller(ctx context.Context, client auth.ClientI, raw services.UnknownResource) error {
|
||||
inst, err := services.UnmarshalInstaller(raw.Raw)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
err = client.SetInstaller(ctx, inst)
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
// Delete deletes resource by name
|
||||
func (rc *ResourceCommand) Delete(ctx context.Context, client auth.ClientI) (err error) {
|
||||
singletonResources := []string{
|
||||
types.KindClusterAuthPreference,
|
||||
types.KindClusterNetworkingConfig,
|
||||
types.KindSessionRecordingConfig,
|
||||
types.KindInstaller,
|
||||
}
|
||||
if !apiutils.SliceContainsStr(singletonResources, rc.ref.Kind) && (rc.ref.Kind == "" || rc.ref.Name == "") {
|
||||
return trace.BadParameter("provide a full resource name to delete, for example:\n$ tctl rm cluster/east\n")
|
||||
|
@ -800,6 +812,12 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client auth.ClientI) (err
|
|||
return trace.NotFound("kubernetes server %q not found", rc.ref.Name)
|
||||
}
|
||||
fmt.Printf("kubernetes server %q has been deleted\n", rc.ref.Name)
|
||||
case types.KindInstaller:
|
||||
err := client.DeleteInstaller(ctx)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
fmt.Printf("%s has been reset to a default value\n", types.KindInstaller)
|
||||
default:
|
||||
return trace.BadParameter("deleting resources of type %q is not supported", rc.ref.Kind)
|
||||
}
|
||||
|
@ -1287,6 +1305,15 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client auth.Client
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &tokenCollection{tokens: []types.ProvisionToken{token}}, nil
|
||||
case types.KindInstaller:
|
||||
if rc.ref.Name != "" {
|
||||
return nil, trace.BadParameter("installer is a singleton resource, use `tctl get %v` to fetch it", types.KindInstaller)
|
||||
}
|
||||
inst, err := client.GetInstaller(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return &installerCollection{inst}, nil
|
||||
}
|
||||
return nil, trace.BadParameter("getting %q is not supported", rc.ref.String())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue