github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/discoveryconfig/discoveryconfig.go (about) 1 /* 2 Copyright 2023 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package discoveryconfig 18 19 import ( 20 "time" 21 22 "github.com/gravitational/trace" 23 24 "github.com/gravitational/teleport/api/types" 25 "github.com/gravitational/teleport/api/types/compare" 26 "github.com/gravitational/teleport/api/types/header" 27 "github.com/gravitational/teleport/api/types/header/convert/legacy" 28 "github.com/gravitational/teleport/api/utils" 29 ) 30 31 var _ compare.IsEqual[*DiscoveryConfig] = (*DiscoveryConfig)(nil) 32 33 // DiscoveryConfig describes extra discovery matchers that are added to DiscoveryServices that share the same Discovery Group. 34 type DiscoveryConfig struct { 35 // ResourceHeader is the common resource header for all resources. 36 header.ResourceHeader 37 38 // Spec is the specification for the discovery config. 39 Spec Spec `json:"spec" yaml:"spec"` 40 41 // Status is the status for the discovery config. 42 Status Status `json:"status" yaml:"status"` 43 } 44 45 // Spec is the specification for a discovery config. 46 type Spec struct { 47 // DiscoveryGroup is the Discovery Group for the current DiscoveryConfig. 48 // DiscoveryServices should include all the matchers if the DiscoveryGroup matches with their own group. 49 DiscoveryGroup string `json:"discovery_group" yaml:"discovery_group"` 50 51 // AWS is a list of matchers for the supported resources in AWS. 52 AWS []types.AWSMatcher `json:"aws,omitempty" yaml:"aws"` 53 // Azure is a list of matchers for the supported resources in Azure. 54 Azure []types.AzureMatcher `json:"azure,omitempty" yaml:"azure"` 55 // GCP is a list of matchers for the supported resources in GCP. 56 GCP []types.GCPMatcher `json:"gcp,omitempty" yaml:"gcp"` 57 // Kube is a list of matchers for the supported resources in Kubernetes. 58 Kube []types.KubernetesMatcher `json:"kube,omitempty" yaml:"kube"` 59 // AccessGraph is the configuration for the Access Graph Cloud sync. 60 AccessGraph *types.AccessGraphSync `json:"access_graph,omitempty" yaml:"access_graph"` 61 } 62 63 // Equal checks if the discovery config is equal to another. 64 // Deprecated: use IsEqual. 65 func (m *DiscoveryConfig) Equal(n *DiscoveryConfig) bool { 66 return m.IsEqual(n) 67 } 68 69 // IsEqual checks if the discovery config is equal to another. 70 func (m *DiscoveryConfig) IsEqual(n *DiscoveryConfig) bool { 71 return deriveTeleportEqualDiscoveryConfig(m, n) 72 } 73 74 // Status holds dynamic information about the discovery configuration 75 // running status such as errors, state and count of the resources. 76 type Status struct { 77 // State is the current state of the discovery config. 78 State string `json:"state" yaml:"state"` 79 // ErrorMessage holds the error message when state is DISCOVERY_CONFIG_STATE_ERROR. 80 ErrorMessage *string `json:"error_message,omitempty" yaml:"error_message,omitempty"` 81 // DiscoveredResources holds the count of the discovered resources in the previous iteration. 82 DiscoveredResources uint64 `json:"discovered_resources" yaml:"discovered_resources"` 83 // LastSyncTime is the timestamp when the Discovery Config was last sync. 84 LastSyncTime time.Time `json:"last_sync_time,omitempty" yaml:"last_sync_time,omitempty"` 85 } 86 87 // NewDiscoveryConfig will create a new discovery config. 88 func NewDiscoveryConfig(metadata header.Metadata, spec Spec) (*DiscoveryConfig, error) { 89 discoveryConfig := &DiscoveryConfig{ 90 ResourceHeader: header.ResourceHeaderFromMetadata(metadata), 91 Spec: spec, 92 } 93 94 if err := discoveryConfig.CheckAndSetDefaults(); err != nil { 95 return nil, trace.Wrap(err) 96 } 97 98 return discoveryConfig, nil 99 } 100 101 // CheckAndSetDefaults validates fields and populates empty fields with default values. 102 func (a *DiscoveryConfig) CheckAndSetDefaults() error { 103 a.SetKind(types.KindDiscoveryConfig) 104 a.SetVersion(types.V1) 105 106 if err := a.ResourceHeader.CheckAndSetDefaults(); err != nil { 107 return trace.Wrap(err) 108 } 109 110 if a.Spec.DiscoveryGroup == "" { 111 return trace.BadParameter("discovery config group required") 112 } 113 114 if a.Spec.AWS == nil { 115 a.Spec.AWS = make([]types.AWSMatcher, 0) 116 } 117 for i := range a.Spec.AWS { 118 if err := a.Spec.AWS[i].CheckAndSetDefaults(); err != nil { 119 return trace.Wrap(err) 120 } 121 } 122 123 if a.Spec.Azure == nil { 124 a.Spec.Azure = make([]types.AzureMatcher, 0) 125 } 126 for i := range a.Spec.Azure { 127 if err := a.Spec.Azure[i].CheckAndSetDefaults(); err != nil { 128 return trace.Wrap(err) 129 } 130 } 131 132 if a.Spec.GCP == nil { 133 a.Spec.GCP = make([]types.GCPMatcher, 0) 134 } 135 for i := range a.Spec.GCP { 136 if err := a.Spec.GCP[i].CheckAndSetDefaults(); err != nil { 137 return trace.Wrap(err) 138 } 139 } 140 141 if a.Spec.Kube == nil { 142 a.Spec.Kube = make([]types.KubernetesMatcher, 0) 143 } 144 for i := range a.Spec.Kube { 145 if err := a.Spec.Kube[i].CheckAndSetDefaults(); err != nil { 146 return trace.Wrap(err) 147 } 148 } 149 150 if a.Spec.AccessGraph != nil { 151 if err := a.Spec.AccessGraph.CheckAndSetDefaults(); err != nil { 152 return trace.Wrap(err) 153 } 154 } 155 156 return nil 157 } 158 159 // GetDiscoveryGroup returns the DiscoveryGroup from the discovery config. 160 func (a *DiscoveryConfig) GetDiscoveryGroup() string { 161 return a.Spec.DiscoveryGroup 162 } 163 164 // GetMetadata returns metadata. This is specifically for conforming to the Resource interface, 165 // and should be removed when possible. 166 func (a *DiscoveryConfig) GetMetadata() types.Metadata { 167 return legacy.FromHeaderMetadata(a.Metadata) 168 } 169 170 // MatchSearch goes through select field values of a resource 171 // and tries to match against the list of search values. 172 func (a *DiscoveryConfig) MatchSearch(values []string) bool { 173 fieldVals := append(utils.MapToStrings(a.GetAllLabels()), a.GetName(), a.GetDiscoveryGroup()) 174 return types.MatchSearch(fieldVals, values, nil) 175 } 176 177 // CloneResource returns a copy of the resource as types.ResourceWithLabels. 178 func (a *DiscoveryConfig) CloneResource() types.ResourceWithLabels { 179 var copy *DiscoveryConfig 180 utils.StrictObjectToStruct(a, ©) 181 return copy 182 }