diff --git a/connection/sftp.go b/connection/sftp.go index f92f9753..e419268b 100644 --- a/connection/sftp.go +++ b/connection/sftp.go @@ -11,9 +11,9 @@ type SFTPConnection struct { // ConnectionName of the connection. It'll be used to populate the connection fields. ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` // Port for the SSH server. Defaults to 22 - Port int `yaml:"port,omitempty" json:"port,omitempty"` - Host string `yaml:"host" json:"host"` - Authentication `yaml:",inline" json:",inline"` + Port int `yaml:"port,omitempty" json:"port,omitempty"` + Host string `yaml:"host" json:"host"` + types.Authentication `yaml:",inline" json:",inline"` } func (c *SFTPConnection) HydrateConnection(ctx ConnectionContext) (found bool, err error) { @@ -27,7 +27,7 @@ func (c *SFTPConnection) HydrateConnection(ctx ConnectionContext) (found bool, e } c.Host = connection.URL - c.Authentication = Authentication{ + c.Authentication = types.Authentication{ Username: types.EnvVar{ValueStatic: connection.Username}, Password: types.EnvVar{ValueStatic: connection.Password}, } diff --git a/connection/smb.go b/connection/smb.go index ce09d7c5..17a482d0 100644 --- a/connection/smb.go +++ b/connection/smb.go @@ -11,8 +11,8 @@ type SMBConnection struct { // ConnectionName of the connection. It'll be used to populate the connection fields. ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` //Port on which smb server is running. Defaults to 445 - Port int `yaml:"port,omitempty" json:"port,omitempty"` - Authentication `yaml:",inline" json:",inline"` + Port int `yaml:"port,omitempty" json:"port,omitempty"` + types.Authentication `yaml:",inline" json:",inline"` //Domain... Domain string `yaml:"domain,omitempty" json:"domain,omitempty"` } @@ -34,7 +34,7 @@ func (c *SMBConnection) HydrateConnection(ctx ConnectionContext) (found bool, er return false, nil } - c.Authentication = Authentication{ + c.Authentication = types.Authentication{ Username: types.EnvVar{ValueStatic: connection.Username}, Password: types.EnvVar{ValueStatic: connection.Password}, } diff --git a/connection/zz_generated.deepcopy.go b/connection/zz_generated.deepcopy.go index 7479e8a9..6eb10765 100644 --- a/connection/zz_generated.deepcopy.go +++ b/connection/zz_generated.deepcopy.go @@ -26,23 +26,6 @@ func (in *AWSConnection) DeepCopy() *AWSConnection { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Authentication) DeepCopyInto(out *Authentication) { - *out = *in - in.Username.DeepCopyInto(&out.Username) - in.Password.DeepCopyInto(&out.Password) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication. -func (in *Authentication) DeepCopy() *Authentication { - if in == nil { - return nil - } - out := new(Authentication) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GCPConnection) DeepCopyInto(out *GCPConnection) { *out = *in diff --git a/models/connections.go b/models/connections.go index ad414fe2..cf4c4f03 100644 --- a/models/connections.go +++ b/models/connections.go @@ -81,7 +81,7 @@ type Connection struct { URL string `gorm:"column:url" json:"url,omitempty" faker:"url" template:"true"` Username string `gorm:"column:username" json:"username,omitempty" faker:"username" ` Password string `gorm:"column:password" json:"password,omitempty" faker:"password" ` - Properties types.JSONStringMap `gorm:"column:properties" json:"properties,omitempty" faker:"-" ` + Properties types.JSONStringMap `gorm:"column:properties" json:"properties,omitempty" faker:"-" template:"true"` Certificate string `gorm:"column:certificate" json:"certificate,omitempty" faker:"-" ` InsecureTLS bool `gorm:"column:insecure_tls;default:false" json:"insecure_tls,omitempty" faker:"-" ` CreatedAt time.Time `gorm:"column:created_at;default:now();<-:create" json:"created_at,omitempty" faker:"-" ` @@ -123,6 +123,16 @@ func (c Connection) AsMap(removeFields ...string) map[string]any { return asMap(c, removeFields...) } +// Auth method only works for a hydrated connection +func (c Connection) Auth() (types.Authentication, error) { + auth := types.Authentication{} + auth.Username.ValueStatic = c.Username + auth.Password.ValueStatic = c.Password + auth.Bearer.ValueStatic = c.Properties["bearer"] + err := auth.OAuth.PopulateFromProperties(c.Properties) + return auth, err +} + func (c Connection) Merge(ctx types.GetEnvVarFromCache, from any) (*Connection, error) { if v, ok := from.(types.WithUsernamePassword); ok { username := v.GetUsername() diff --git a/models/zz_generated.deepcopy.go b/models/zz_generated.deepcopy.go index eb99ec1d..fc629ae8 100644 --- a/models/zz_generated.deepcopy.go +++ b/models/zz_generated.deepcopy.go @@ -25,11 +25,21 @@ func (in *Link) DeepCopy() *Link { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Property) DeepCopyInto(out *Property) { *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(int64) + **out = **in + } if in.Max != nil { in, out := &in.Max, &out.Max *out = new(int64) **out = **in } + if in.Min != nil { + in, out := &in.Min, &out.Min + *out = new(int64) + **out = **in + } if in.Links != nil { in, out := &in.Links, &out.Links *out = make([]Link, len(*in)) diff --git a/connection/auth.go b/types/auth.go similarity index 54% rename from connection/auth.go rename to types/auth.go index 050fd901..409a9dd6 100644 --- a/connection/auth.go +++ b/types/auth.go @@ -1,19 +1,19 @@ -package connection +package types import ( "strings" - - "github.com/flanksource/duty/types" ) // +kubebuilder:object:generate=true type Authentication struct { - Username types.EnvVar `yaml:"username,omitempty" json:"username,omitempty"` - Password types.EnvVar `yaml:"password,omitempty" json:"password,omitempty"` + Username EnvVar `yaml:"username,omitempty" json:"username,omitempty"` + Password EnvVar `yaml:"password,omitempty" json:"password,omitempty"` + Bearer EnvVar `yaml:"bearer,omitempty" json:"bearer,omitempty"` + OAuth OAuth `yaml:"oauth,omitempty" json:"oauth,omitempty"` } func (auth Authentication) IsEmpty() bool { - return auth.Username.IsEmpty() && auth.Password.IsEmpty() + return (auth.Username.IsEmpty() && auth.Password.IsEmpty()) && auth.OAuth.IsEmpty() && auth.Bearer.IsEmpty() } func (auth Authentication) GetUsername() string { diff --git a/types/oauth.go b/types/oauth.go new file mode 100644 index 00000000..6b39baf6 --- /dev/null +++ b/types/oauth.go @@ -0,0 +1,56 @@ +package types + +import ( + "encoding/json" + "fmt" + + "github.com/flanksource/commons/collections" +) + +// +kubebuilder:object:generate=true +type OAuth struct { + ClientID EnvVar `json:"clientID,omitempty"` + ClientSecret EnvVar `json:"clientSecret,omitempty"` + Scopes []string `json:"scope,omitempty" yaml:"scope,omitempty"` + TokenURL string `json:"tokenURL,omitempty" yaml:"tokenURL,omitempty"` + Params map[string]string `json:"params,omitempty" yaml:"params,omitempty"` +} + +func (o OAuth) IsEmpty() bool { + return o.ClientID.IsEmpty() || o.ClientSecret.IsEmpty() || o.TokenURL == "" +} + +// PopulateFromProperties needs properties to be hydrated +func (o *OAuth) PopulateFromProperties(props map[string]string) error { + o.ClientID.ValueStatic = props["clientID"] + o.ClientSecret.ValueStatic = props["clientSecret"] + o.TokenURL = props["tokenURL"] + if props["scope"] != "" { + if err := json.Unmarshal([]byte(props["scopes"]), &o.Scopes); err != nil { + return fmt.Errorf("error unmarshaling scopes:%s in oauth: %w", props["scopes"], err) + } + } + if props["params"] != "" { + if err := json.Unmarshal([]byte(props["params"]), &o.Params); err != nil { + return fmt.Errorf("error unmarshaling params:%s in oauth: %w", props["params"], err) + } + } + return nil +} + +func (o OAuth) AsProperties() JSONStringMap { + var scopes, params string + if o.Scopes != nil { + scopes, _ = collections.StructToJSON(o.Scopes) + } + if o.Params != nil { + params, _ = collections.StructToJSON(o.Params) + } + return map[string]string{ + "clientID": o.ClientID.String(), + "clientSecret": o.ClientSecret.String(), + "tokenURL": o.TokenURL, + "scopes": scopes, + "params": params, + } +} diff --git a/types/zz_generated.deepcopy.go b/types/zz_generated.deepcopy.go index 3e80e51c..15a09cd1 100644 --- a/types/zz_generated.deepcopy.go +++ b/types/zz_generated.deepcopy.go @@ -8,6 +8,25 @@ import ( "encoding/json" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Authentication) DeepCopyInto(out *Authentication) { + *out = *in + in.Username.DeepCopyInto(&out.Username) + in.Password.DeepCopyInto(&out.Password) + in.Bearer.DeepCopyInto(&out.Bearer) + in.OAuth.DeepCopyInto(&out.OAuth) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication. +func (in *Authentication) DeepCopy() *Authentication { + if in == nil { + return nil + } + out := new(Authentication) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentCheck) DeepCopyInto(out *ComponentCheck) { *out = *in @@ -192,9 +211,43 @@ func (in *LogSelector) DeepCopy() *LogSelector { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OAuth) DeepCopyInto(out *OAuth) { + *out = *in + in.ClientID.DeepCopyInto(&out.ClientID) + in.ClientSecret.DeepCopyInto(&out.ClientSecret) + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAuth. +func (in *OAuth) DeepCopy() *OAuth { + if in == nil { + return nil + } + out := new(OAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Property) DeepCopyInto(out *Property) { *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(int64) + **out = **in + } if in.Max != nil { in, out := &in.Max, &out.Max *out = new(int64)