Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions sysdig/internal/client/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -1201,3 +1201,80 @@ type ZoneScope struct {
TargetType string `json:"targetType"`
Rules string `json:"rules"`
}

// SSO OpenID Connect configuration - combines base SSO fields with OpenID-specific config
type SSOOpenID struct {
// Response-only identification fields
ID int `json:"id,omitempty"`
Version int `json:"version,omitempty"`
DateCreated string `json:"dateCreated,omitempty"`
LastUpdated string `json:"lastUpdated,omitempty"`

// Base SSO fields (root level in API)
Product string `json:"product,omitempty"`
IsActive bool `json:"isActive"`
CreateUserOnLogin bool `json:"createUserOnLogin"`
IsSingleLogoutEnabled bool `json:"isSingleLogoutEnabled"`
IsGroupMappingEnabled bool `json:"isGroupMappingEnabled"`
GroupMappingAttributeName string `json:"groupMappingAttributeName,omitempty"`
IntegrationName string `json:"integrationName,omitempty"`

// OpenID-specific config (nested in "config" in API)
Config *SSOOpenIDConfig `json:"config,omitempty"`
}

// SSOOpenIDConfig contains OpenID-specific fields that go inside the "config" block
type SSOOpenIDConfig struct {
Type string `json:"type"` // "OPENID"
IssuerURL string `json:"issuerUrl"`
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret,omitempty"`
IsMetadataDiscoveryEnabled bool `json:"isMetadataDiscoveryEnabled"`
Metadata *OpenIDMetadata `json:"metadata,omitempty"`
GroupAttributeName string `json:"groupAttributeName,omitempty"`
IsAdditionalScopesCheckEnabled bool `json:"isAdditionalScopesCheckEnabled"`
AdditionalScopes []string `json:"additionalScopes,omitempty"`
}

type OpenIDMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorizationEndpoint"`
TokenEndpoint string `json:"tokenEndpoint"`
JwksURI string `json:"jwksUri"`
TokenAuthMethod string `json:"tokenAuthMethod"`
EndSessionEndpoint string `json:"endSessionEndpoint,omitempty"`
UserInfoEndpoint string `json:"userInfoEndpoint,omitempty"`
}

// SSO SAML configuration - combines base SSO fields with SAML-specific config
type SSOSaml struct {
// Response-only identification fields
ID int `json:"id,omitempty"`
Version int `json:"version,omitempty"`
DateCreated string `json:"dateCreated,omitempty"`
LastUpdated string `json:"lastUpdated,omitempty"`

// Base SSO fields (root level in API)
Product string `json:"product,omitempty"`
IsActive bool `json:"isActive"`
CreateUserOnLogin bool `json:"createUserOnLogin"`
IsSingleLogoutEnabled bool `json:"isSingleLogoutEnabled"`
IsGroupMappingEnabled bool `json:"isGroupMappingEnabled"`
GroupMappingAttributeName string `json:"groupMappingAttributeName,omitempty"`
IntegrationName string `json:"integrationName,omitempty"`

// SAML-specific config (nested in "config" in API)
Config *SSOSamlConfig `json:"config,omitempty"`
}

// SSOSamlConfig contains SAML-specific fields that go inside the "config" block
type SSOSamlConfig struct {
Type string `json:"type"` // "SAML"
MetadataURL string `json:"metadataUrl,omitempty"`
MetadataXML string `json:"metadataXml,omitempty"`
EmailParameter string `json:"emailParameter"`
IsSignatureValidationEnabled *bool `json:"isSignatureValidationEnabled,omitempty"`
IsSignedAssertionEnabled *bool `json:"isSignedAssertionEnabled,omitempty"`
IsDestinationVerificationEnabled *bool `json:"isDestinationVerificationEnabled,omitempty"`
IsEncryptionSupportEnabled *bool `json:"isEncryptionSupportEnabled,omitempty"`
}
126 changes: 126 additions & 0 deletions sysdig/internal/client/v2/sso_openid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package v2

import (
"context"
"errors"
"fmt"
"net/http"
)

var ErrSSOOpenIDNotFound = errors.New("SSO OpenID configuration not found")

const (
createSSOOpenIDPath = "%s/platform/v1/sso-settings/"
getSSOOpenIDPath = "%s/platform/v1/sso-settings/%d"
updateSSOOpenIDPath = "%s/platform/v1/sso-settings/%d"
deleteSSOOpenIDPath = "%s/platform/v1/sso-settings/%d"
)

type SSOOpenIDInterface interface {
Base
CreateSSOOpenID(ctx context.Context, sso *SSOOpenID) (*SSOOpenID, error)
GetSSOOpenID(ctx context.Context, id int) (*SSOOpenID, error)
UpdateSSOOpenID(ctx context.Context, id int, sso *SSOOpenID) (*SSOOpenID, error)
DeleteSSOOpenID(ctx context.Context, id int) error
}

func (c *Client) CreateSSOOpenID(ctx context.Context, sso *SSOOpenID) (result *SSOOpenID, err error) {
payload, err := Marshal(sso)
if err != nil {
return nil, err
}

response, err := c.requester.Request(ctx, http.MethodPost, c.createSSOOpenIDURL(), payload)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOOpenID](response.Body)
}

func (c *Client) GetSSOOpenID(ctx context.Context, id int) (result *SSOOpenID, err error) {
response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOOpenIDURL(id), nil)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode == http.StatusNotFound {
return nil, ErrSSOOpenIDNotFound
}
if response.StatusCode != http.StatusOK {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOOpenID](response.Body)
}

func (c *Client) UpdateSSOOpenID(ctx context.Context, id int, sso *SSOOpenID) (result *SSOOpenID, err error) {
payload, err := Marshal(sso)
if err != nil {
return nil, err
}

response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOOpenIDURL(id), payload)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusOK {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOOpenID](response.Body)
}

func (c *Client) DeleteSSOOpenID(ctx context.Context, id int) (err error) {
response, err := c.requester.Request(ctx, http.MethodDelete, c.deleteSSOOpenIDURL(id), nil)
if err != nil {
return err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound {
return c.ErrorFromResponse(response)
}

return nil
}

func (c *Client) createSSOOpenIDURL() string {
return fmt.Sprintf(createSSOOpenIDPath, c.config.url)
}

func (c *Client) getSSOOpenIDURL(id int) string {
return fmt.Sprintf(getSSOOpenIDPath, c.config.url, id)
}

func (c *Client) updateSSOOpenIDURL(id int) string {
return fmt.Sprintf(updateSSOOpenIDPath, c.config.url, id)
}

func (c *Client) deleteSSOOpenIDURL(id int) string {
return fmt.Sprintf(deleteSSOOpenIDPath, c.config.url, id)
}
126 changes: 126 additions & 0 deletions sysdig/internal/client/v2/sso_saml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package v2

import (
"context"
"errors"
"fmt"
"net/http"
)

var ErrSSOSamlNotFound = errors.New("SSO SAML configuration not found")

const (
createSSOSamlPath = "%s/platform/v1/sso-settings/"
getSSOSamlPath = "%s/platform/v1/sso-settings/%d"
updateSSOSamlPath = "%s/platform/v1/sso-settings/%d"
deleteSSOSamlPath = "%s/platform/v1/sso-settings/%d"
)

type SSOSamlInterface interface {
Base
CreateSSOSaml(ctx context.Context, sso *SSOSaml) (*SSOSaml, error)
GetSSOSaml(ctx context.Context, id int) (*SSOSaml, error)
UpdateSSOSaml(ctx context.Context, id int, sso *SSOSaml) (*SSOSaml, error)
DeleteSSOSaml(ctx context.Context, id int) error
}

func (c *Client) CreateSSOSaml(ctx context.Context, sso *SSOSaml) (result *SSOSaml, err error) {
payload, err := Marshal(sso)
if err != nil {
return nil, err
}

response, err := c.requester.Request(ctx, http.MethodPost, c.createSSOSamlURL(), payload)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOSaml](response.Body)
}

func (c *Client) GetSSOSaml(ctx context.Context, id int) (result *SSOSaml, err error) {
response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOSamlURL(id), nil)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode == http.StatusNotFound {
return nil, ErrSSOSamlNotFound
}
if response.StatusCode != http.StatusOK {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOSaml](response.Body)
}

func (c *Client) UpdateSSOSaml(ctx context.Context, id int, sso *SSOSaml) (result *SSOSaml, err error) {
payload, err := Marshal(sso)
if err != nil {
return nil, err
}

response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOSamlURL(id), payload)
if err != nil {
return nil, err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusOK {
return nil, c.ErrorFromResponse(response)
}

return Unmarshal[*SSOSaml](response.Body)
}

func (c *Client) DeleteSSOSaml(ctx context.Context, id int) (err error) {
response, err := c.requester.Request(ctx, http.MethodDelete, c.deleteSSOSamlURL(id), nil)
if err != nil {
return err
}
defer func() {
if dErr := response.Body.Close(); dErr != nil {
err = fmt.Errorf("unable to close response body: %w", dErr)
}
}()

if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound {
return c.ErrorFromResponse(response)
}

return nil
}

func (c *Client) createSSOSamlURL() string {
return fmt.Sprintf(createSSOSamlPath, c.config.url)
}

func (c *Client) getSSOSamlURL(id int) string {
return fmt.Sprintf(getSSOSamlPath, c.config.url, id)
}

func (c *Client) updateSSOSamlURL(id int) string {
return fmt.Sprintf(updateSSOSamlPath, c.config.url, id)
}

func (c *Client) deleteSSOSamlURL(id int) string {
return fmt.Sprintf(deleteSSOSamlPath, c.config.url, id)
}
2 changes: 2 additions & 0 deletions sysdig/internal/client/v2/sysdig.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type SysdigCommon interface {
GroupMappingInterface
IPFilteringSettingsInterface
IPFiltersInterface
SSOOpenIDInterface
SSOSamlInterface
TeamServiceAccountInterface
}

Expand Down
2 changes: 2 additions & 0 deletions sysdig/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ func (p *SysdigProvider) Provider() *schema.Provider {
"sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(),
"sysdig_ip_filter": resourceSysdigIPFilter(),
"sysdig_ip_filtering_settings": resourceSysdigIPFilteringSettings(),
"sysdig_sso_openid": resourceSysdigSSOOpenID(),
"sysdig_sso_saml": resourceSysdigSSOSaml(),
"sysdig_team_service_account": resourceSysdigTeamServiceAccount(),
"sysdig_user": resourceSysdigUser(),

Expand Down
1 change: 0 additions & 1 deletion sysdig/resource_sysdig_secure_cloud_auth_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,6 @@ func TestAccAWSSecureCloudAuthAccountResponseActions(t *testing.T) {
},
},
})

}

func TestAccAWSSecureCloudAccountThreatDetection(t *testing.T) {
Expand Down
Loading
Loading