diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 930d88ab..735b93f3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -56,5 +56,8 @@ jobs:
ARM_TENANT_ID: ${{ secrets.AZURE_TF_ACCEPTANCE_TEST_ARM_TENANT_ID }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_TF_ACCEPTANCE_TEST_CREDENTIALS }}
GOOGLE_PROJECT_ID: ${{ secrets.GOOGLE_TF_ACCEPTANCE_PROJECT_ID }}
+ SSO_CLIENT_ID: ${{ secrets.SSO_CLIENT_ID }}
+ SSO_CLIENT_SECRET: ${{ secrets.SSO_CLIENT_SECRET }}
+ SSO_DOMAIN: ${{ secrets.SSO_DOMAIN }}
run: make testacc
diff --git a/Makefile b/Makefile
index 55518194..ec3c3926 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ init-examples:
generate-sdk:
@echo "==> Generating castai sdk client"
- @API_TAGS=ExternalClusterAPI,PoliciesAPI,NodeConfigurationAPI,NodeTemplatesAPI,AuthTokenAPI,ScheduledRebalancingAPI,InventoryAPI,UsersAPI,OperationsAPI,EvictorAPI go generate castai/sdk/generate.go
+ @API_TAGS=ExternalClusterAPI,PoliciesAPI,NodeConfigurationAPI,NodeTemplatesAPI,AuthTokenAPI,ScheduledRebalancingAPI,InventoryAPI,UsersAPI,OperationsAPI,EvictorAPI,SSOAPI go generate castai/sdk/generate.go
# The following command also rewrites existing documentation
generate-docs:
@@ -48,4 +48,4 @@ validate-terraform-examples:
terraform validate; \
cd -; \
done \
- done
\ No newline at end of file
+ done
diff --git a/castai/provider.go b/castai/provider.go
index 5c807b46..a31b6e22 100644
--- a/castai/provider.go
+++ b/castai/provider.go
@@ -48,6 +48,7 @@ func Provider(version string) *schema.Provider {
"castai_eks_user_arn": resourceEKSClusterUserARN(),
"castai_reservations": resourceReservations(),
"castai_organization_members": resourceOrganizationMembers(),
+ "castai_sso_connection": resourceSSOConnection(),
},
DataSourcesMap: map[string]*schema.Resource{
diff --git a/castai/resource_sso_connection.go b/castai/resource_sso_connection.go
new file mode 100644
index 00000000..30f9fece
--- /dev/null
+++ b/castai/resource_sso_connection.go
@@ -0,0 +1,309 @@
+package castai
+
+import (
+ "context"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/castai/terraform-provider-castai/castai/sdk"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+ "golang.org/x/crypto/bcrypt"
+)
+
+const (
+ FieldSSOConnectionName = "name"
+ FieldSSOConnectionEmailDomain = "email_domain"
+
+ FieldSSOConnectionAAD = "aad"
+ FieldSSOConnectionADDomain = "ad_domain"
+ FieldSSOConnectionADClientID = "client_id"
+ FieldSSOConnectionADClientSecret = "client_secret"
+
+ FieldSSOConnectionOkta = "okta"
+ FieldSSOConnectionOktaDomain = "okta_domain"
+ FieldSSOConnectionOktaClientID = "client_id"
+ FieldSSOConnectionOktaClientSecret = "client_secret"
+)
+
+func resourceSSOConnection() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceCastaiSSOConnectionCreate,
+ ReadContext: resourceCastaiSSOConnectionRead,
+ UpdateContext: resourceCastaiSSOConnectionUpdate,
+ DeleteContext: resourceCastaiSSOConnectionDelete,
+ CustomizeDiff: resourceCastaiSSOConnectionDiff,
+ Description: "SSO Connection resource allows creating SSO trust relationship with CAST AI.",
+ Timeouts: &schema.ResourceTimeout{
+ Create: schema.DefaultTimeout(3 * time.Minute),
+ Update: schema.DefaultTimeout(3 * time.Minute),
+ Delete: schema.DefaultTimeout(3 * time.Minute),
+ },
+ Schema: map[string]*schema.Schema{
+ FieldSSOConnectionName: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Connection name",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionEmailDomain: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Email domain of the connection",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionAAD: {
+ Type: schema.TypeList,
+ MaxItems: 1,
+ MinItems: 1,
+ Optional: true,
+ Description: "Azure AD connector",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ FieldSSOConnectionADDomain: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Azure AD domain",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionADClientID: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Azure AD client ID",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionADClientSecret: {
+ Type: schema.TypeString,
+ Sensitive: true,
+ Required: true,
+ Description: "Azure AD client secret",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ DiffSuppressFunc: func(_, oldValue, newValue string, _ *schema.ResourceData) bool {
+ decodedSecret, err := base64.StdEncoding.DecodeString(oldValue)
+ if err != nil {
+ return false
+ }
+ return bcrypt.CompareHashAndPassword(decodedSecret, []byte(newValue)) == nil
+ },
+ },
+ },
+ },
+ },
+ FieldSSOConnectionOkta: {
+ Type: schema.TypeList,
+ MaxItems: 1,
+ MinItems: 1,
+ Optional: true,
+ Description: "Okta connector",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ FieldSSOConnectionOktaDomain: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Okta domain",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionOktaClientID: {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Okta client ID",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ FieldSSOConnectionOktaClientSecret: {
+ Type: schema.TypeString,
+ Required: true,
+ Sensitive: true,
+ Description: "Okta client secret",
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ DiffSuppressFunc: func(_, oldValue, newValue string, _ *schema.ResourceData) bool {
+ decodedSecret, err := base64.StdEncoding.DecodeString(oldValue)
+ if err != nil {
+ return false
+ }
+ return bcrypt.CompareHashAndPassword(decodedSecret, []byte(newValue)) == nil
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func resourceCastaiSSOConnectionCreate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ client := meta.(*ProviderConfig).api
+
+ req := sdk.CastaiSsoV1beta1CreateSSOConnection{
+ Name: data.Get(FieldSSOConnectionName).(string),
+ EmailDomain: data.Get(FieldSSOConnectionEmailDomain).(string),
+ }
+
+ if v, ok := data.Get(FieldSSOConnectionAAD).([]any); ok && len(v) > 0 {
+ req.Aad = toADConnector(v[0].(map[string]any))
+ }
+
+ if v, ok := data.Get(FieldSSOConnectionOkta).([]any); ok && len(v) > 0 {
+ req.Okta = toOktaConnector(v[0].(map[string]any))
+ }
+
+ resp, err := client.SSOAPICreateSSOConnectionWithResponse(ctx, req)
+ if err := sdk.CheckOKResponse(resp, err); err != nil {
+ return diag.Errorf("creating sso connection: %v", err)
+ }
+
+ if err := checkSSOStatus(resp.JSON200); err != nil {
+ return diag.FromErr(err)
+ }
+
+ data.SetId(*resp.JSON200.Id)
+
+ return resourceCastaiSSOConnectionRead(ctx, data, meta)
+}
+
+func resourceCastaiSSOConnectionRead(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ if data.Id() == "" {
+ return nil
+ }
+
+ client := meta.(*ProviderConfig).api
+ resp, err := client.SSOAPIGetSSOConnectionWithResponse(ctx, data.Id())
+ if err := sdk.CheckOKResponse(resp, err); err != nil {
+ return diag.Errorf("retrieving sso connection: %v", err)
+ }
+
+ connection := resp.JSON200
+
+ if err := data.Set(FieldSSOConnectionName, connection.Name); err != nil {
+ return diag.Errorf("setting connection name: %v", err)
+ }
+ if err := data.Set(FieldSSOConnectionEmailDomain, connection.EmailDomain); err != nil {
+ return diag.Errorf("setting email domain: %v", err)
+ }
+
+ return nil
+}
+
+func resourceCastaiSSOConnectionUpdate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ if !data.HasChanges(
+ FieldSSOConnectionName,
+ FieldSSOConnectionEmailDomain,
+ FieldSSOConnectionAAD,
+ FieldSSOConnectionOkta,
+ ) {
+ return nil
+ }
+
+ client := meta.(*ProviderConfig).api
+ req := sdk.CastaiSsoV1beta1UpdateSSOConnection{}
+
+ if v, ok := data.GetOk(FieldSSOConnectionName); ok {
+ req.Name = toPtr(v.(string))
+ }
+ if v, ok := data.GetOk(FieldSSOConnectionEmailDomain); ok {
+ req.EmailDomain = toPtr(v.(string))
+ }
+
+ if v, ok := data.Get(FieldSSOConnectionAAD).([]any); ok && len(v) > 0 {
+ req.Aad = toADConnector(v[0].(map[string]any))
+ }
+
+ if v, ok := data.Get(FieldSSOConnectionOkta).([]any); ok && len(v) > 0 {
+ req.Okta = toOktaConnector(v[0].(map[string]any))
+ }
+
+ resp, err := client.SSOAPIUpdateSSOConnectionWithResponse(ctx, data.Id(), req)
+ if err := sdk.CheckOKResponse(resp, err); err != nil {
+ return diag.Errorf("updating sso connection: %v", err)
+ }
+
+ if err := checkSSOStatus(resp.JSON200); err != nil {
+ return diag.FromErr(err)
+ }
+
+ return resourceCastaiSSOConnectionRead(ctx, data, meta)
+}
+
+func resourceCastaiSSOConnectionDelete(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ client := meta.(*ProviderConfig).api
+
+ resp, err := client.SSOAPIDeleteSSOConnectionWithResponse(ctx, data.Id())
+ if err := sdk.CheckOKResponse(resp, err); err != nil {
+ return diag.Errorf("deleting sso connection: %v", err)
+ }
+
+ return nil
+}
+
+func checkSSOStatus(input *sdk.CastaiSsoV1beta1SSOConnection) error {
+ if input == nil && input.Status == nil {
+ return nil
+ }
+
+ if *input.Status == sdk.STATUSACTIVE {
+ return nil
+ }
+
+ if input.Error == nil {
+ return fmt.Errorf("invalid SSO connection status: %s", *input.Status)
+ }
+
+ return fmt.Errorf("SSO connection status: %s failed with error: %s", *input.Status, *input.Error)
+}
+
+func resourceCastaiSSOConnectionDiff(_ context.Context, rd *schema.ResourceDiff, _ interface{}) error {
+ connectors := 0
+ if v, ok := rd.Get(FieldSSOConnectionAAD).([]any); ok && len(v) > 0 {
+ connectors++
+ }
+
+ if v, ok := rd.Get(FieldSSOConnectionOkta).([]any); ok && len(v) > 0 {
+ connectors++
+ }
+
+ if connectors != 1 {
+ return errors.New("only 1 connector can be configured")
+ }
+
+ return nil
+}
+
+func toADConnector(obj map[string]any) *sdk.CastaiSsoV1beta1AzureAAD {
+ if obj == nil {
+ return nil
+ }
+
+ out := &sdk.CastaiSsoV1beta1AzureAAD{}
+ if v, ok := obj[FieldSSOConnectionADDomain].(string); ok {
+ out.AdDomain = v
+ }
+ if v, ok := obj[FieldSSOConnectionADClientID].(string); ok {
+ out.ClientId = v
+ }
+ if v, ok := obj[FieldSSOConnectionADClientSecret].(string); ok {
+ out.ClientSecret = toPtr(v)
+ }
+
+ return out
+}
+
+func toOktaConnector(obj map[string]any) *sdk.CastaiSsoV1beta1Okta {
+ if obj == nil {
+ return nil
+ }
+
+ out := &sdk.CastaiSsoV1beta1Okta{}
+ if v, ok := obj[FieldSSOConnectionOktaDomain].(string); ok {
+ out.OktaDomain = v
+ }
+ if v, ok := obj[FieldSSOConnectionOktaClientID].(string); ok {
+ out.ClientId = v
+ }
+ if v, ok := obj[FieldSSOConnectionOktaClientSecret].(string); ok {
+ out.ClientSecret = toPtr(v)
+ }
+
+ return out
+}
diff --git a/castai/resource_sso_connection_test.go b/castai/resource_sso_connection_test.go
new file mode 100644
index 00000000..81ca46cf
--- /dev/null
+++ b/castai/resource_sso_connection_test.go
@@ -0,0 +1,518 @@
+package castai
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/castai/terraform-provider-castai/castai/sdk"
+ mock_sdk "github.com/castai/terraform-provider-castai/castai/sdk/mock"
+ "github.com/golang/mock/gomock"
+ "github.com/hashicorp/go-cty/cty"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAccResourceSSOConnection(t *testing.T) {
+ rName := fmt.Sprintf("%v-sso-connection-%v", ResourcePrefix, acctest.RandString(8))
+ resourceName := "castai_sso_connection.test"
+
+ clientID := os.Getenv("SSO_CLIENT_ID")
+ clientSecret := os.Getenv("SSO_CLIENT_SECRET")
+ domain := os.Getenv("SSO_DOMAIN")
+
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: providerFactories,
+ CheckDestroy: testAccSSOConnectionConfigurationDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccCreateSSOConnectionConfig(rName, clientID, clientSecret, domain),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "name", rName),
+ resource.TestCheckResourceAttr(resourceName, "email_domain", "aad_connection@test.com"),
+ resource.TestCheckResourceAttrSet(resourceName, "aad.0.client_id"),
+ resource.TestCheckResourceAttrSet(resourceName, "aad.0.client_secret"),
+ resource.TestCheckResourceAttrSet(resourceName, "aad.0.ad_domain"),
+ ),
+ },
+ },
+ })
+}
+
+func TestSSOConnection_ReadContext(t *testing.T) {
+ readBody := `{"id":"fce35ba2-5c06-4078-8391-1ac8f7ba798b","name":"test_sso","createdAt":"2023-11-02T10:49:14.376757Z","updatedAt":"2023-11-02T10:49:14.450828Z","emailDomain":"test_email","aad":{"adDomain":"test_connector","clientId":"test_client","clientSecret":"test_secret"}}`
+
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ connectionID := "fce35ba2-5c06-4078-8391-1ac8f7ba798b"
+
+ mockClient.EXPECT().
+ SSOAPIGetSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader([]byte(readBody))), Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ resource := resourceSSOConnection()
+ data := resource.Data(
+ terraform.NewInstanceStateShimmedFromValue(cty.ObjectVal(map[string]cty.Value{
+ "id": cty.StringVal(connectionID),
+ }), 0))
+
+ result := resource.ReadContext(context.Background(), data, &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ })
+
+ r := require.New(t)
+ r.Nil(result)
+ r.False(result.HasError())
+ r.Equal("test_sso", data.Get(FieldSSOConnectionName))
+ r.Equal("test_email", data.Get(FieldSSOConnectionEmailDomain))
+}
+
+func TestSSOConnection_CreateADDConnector(t *testing.T) {
+ r := require.New(t)
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ mockClient.EXPECT().
+ SSOAPICreateSSOConnection(gomock.Any(), gomock.Any()).
+ DoAndReturn(func(_ context.Context, body sdk.SSOAPICreateSSOConnectionJSONBody) (*http.Response, error) {
+ got, err := json.Marshal(body)
+ r.NoError(err)
+
+ expected := []byte(`{
+ "aad": {
+ "adDomain": "test_connector",
+ "clientId": "test_client",
+ "clientSecret": "test_secret"
+ },
+ "emailDomain": "test_email",
+ "name": "test_sso"
+}
+`)
+
+ equal, err := JSONBytesEqual(got, expected)
+ r.NoError(err)
+ r.True(equal, fmt.Sprintf("got: %v\n"+
+ "expected: %v\n", string(got), string(expected)))
+
+ return &http.Response{
+ StatusCode: 200,
+ Header: map[string][]string{"Content-Type": {"json"}},
+ Body: io.NopCloser(bytes.NewReader([]byte(`{"id": "b6bfc074-a267-400f-b8f1-db0850c369b1", "status": "STATUS_ACTIVE"}`))),
+ }, nil
+ })
+
+ connectionID := "b6bfc074-a267-400f-b8f1-db0850c369b1"
+ readBody := io.NopCloser(bytes.NewReader([]byte(`{
+ "id": "b6bfc074-a267-400f-b8f1-db0850c369b1",
+ "name": "test_sso",
+ "createdAt": "2023-11-02T10:49:14.376757Z",
+ "updatedAt": "2023-11-02T10:49:14.450828Z",
+ "emailDomain": "test_email",
+ "aad": {
+ "adDomain": "test_connector",
+ "clientId": "test_client",
+ "clientSecret": "test_secret"
+ }
+}`)))
+
+ mockClient.EXPECT().
+ SSOAPIGetSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: readBody, Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ resource := resourceSSOConnection()
+ data := resource.Data(terraform.NewInstanceStateShimmedFromValue(cty.ObjectVal(map[string]cty.Value{
+ FieldSSOConnectionName: cty.StringVal("test_sso"),
+ FieldSSOConnectionEmailDomain: cty.StringVal("test_email"),
+ FieldSSOConnectionAAD: cty.ListVal([]cty.Value{
+ cty.ObjectVal(map[string]cty.Value{
+ FieldSSOConnectionADDomain: cty.StringVal("test_connector"),
+ FieldSSOConnectionADClientID: cty.StringVal("test_client"),
+ FieldSSOConnectionADClientSecret: cty.StringVal("test_secret"),
+ }),
+ }),
+ }), 0))
+
+ result := resource.CreateContext(context.Background(), data, &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ })
+
+ r.Nil(result)
+ r.False(result.HasError())
+ r.Equal("test_sso", data.Get(FieldSSOConnectionName))
+ r.Equal("test_email", data.Get(FieldSSOConnectionEmailDomain))
+ equalADConnector(t, r, data.Get(FieldSSOConnectionAAD), "test_connector", "test_client", "test_secret")
+}
+
+func TestSSOConnection_CreateOktaConnector(t *testing.T) {
+ r := require.New(t)
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ mockClient.EXPECT().
+ SSOAPICreateSSOConnection(gomock.Any(), gomock.Any()).
+ DoAndReturn(func(_ context.Context, body sdk.SSOAPICreateSSOConnectionJSONBody) (*http.Response, error) {
+ got, err := json.Marshal(body)
+ r.NoError(err)
+
+ expected := []byte(`{
+ "okta": {
+ "oktaDomain": "test_connector",
+ "clientId": "test_client",
+ "clientSecret": "test_secret"
+ },
+ "emailDomain": "test_email",
+ "name": "test_sso"
+}`)
+
+ equal, err := JSONBytesEqual(got, expected)
+ r.NoError(err)
+ r.True(equal, fmt.Sprintf("got: %v\n"+
+ "expected: %v\n", string(got), string(expected)))
+
+ return &http.Response{
+ StatusCode: 200,
+ Header: map[string][]string{"Content-Type": {"json"}},
+ Body: io.NopCloser(bytes.NewReader([]byte(`{"id": "b6bfc074-a267-400f-b8f1-db0850c369b1", "status": "STATUS_ACTIVE"}`))),
+ }, nil
+ })
+
+ connectionID := "b6bfc074-a267-400f-b8f1-db0850c369b1"
+ readBody := io.NopCloser(bytes.NewReader([]byte(`{
+ "id": "b6bfc074-a267-400f-b8f1-db0850c369b1",
+ "name": "test_sso",
+ "createdAt": "2023-11-02T10:49:14.376757Z",
+ "updatedAt": "2023-11-02T10:49:14.450828Z",
+ "emailDomain": "test_email",
+ "okta": {
+ "oktaDomain": "test_connector",
+ "clientId": "test_client",
+ "clientSecret": "test_secret"
+ }
+}`)))
+
+ mockClient.EXPECT().
+ SSOAPIGetSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: readBody, Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ resource := resourceSSOConnection()
+ data := resource.Data(terraform.NewInstanceStateShimmedFromValue(cty.ObjectVal(map[string]cty.Value{
+ FieldSSOConnectionName: cty.StringVal("test_sso"),
+ FieldSSOConnectionEmailDomain: cty.StringVal("test_email"),
+ FieldSSOConnectionOkta: cty.ListVal([]cty.Value{
+ cty.ObjectVal(map[string]cty.Value{
+ FieldSSOConnectionOktaDomain: cty.StringVal("test_connector"),
+ FieldSSOConnectionOktaClientID: cty.StringVal("test_client"),
+ FieldSSOConnectionOktaClientSecret: cty.StringVal("test_secret"),
+ }),
+ }),
+ }), 0))
+
+ result := resource.CreateContext(context.Background(), data, &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ })
+
+ r.Nil(result)
+ r.False(result.HasError())
+ r.Equal("test_sso", data.Get(FieldSSOConnectionName))
+ r.Equal("test_email", data.Get(FieldSSOConnectionEmailDomain))
+ equalOktaConnector(t, r, data.Get(FieldSSOConnectionOkta), "test_connector", "test_client", "test_secret")
+}
+
+func TestSSOConnection_UpdateADDConnector(t *testing.T) {
+ r := require.New(t)
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ ctx := context.Background()
+ provider := &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ }
+ connectionID := "b6bfc074-a267-400f-b8f1-db0850c369b1"
+
+ raw := make(map[string]interface{})
+ raw[FieldSSOConnectionName] = "updated_name"
+
+ resource := resourceSSOConnection()
+ data := schema.TestResourceDataRaw(t, resource.Schema, raw)
+ data.SetId(connectionID)
+ r.NoError(data.Set(FieldSSOConnectionAAD, []map[string]interface{}{
+ {
+ FieldSSOConnectionADDomain: "updated_domain",
+ FieldSSOConnectionADClientID: "updated_client_id",
+ FieldSSOConnectionADClientSecret: "updated_client_secret",
+ },
+ }))
+
+ mockClient.EXPECT().SSOAPIUpdateSSOConnection(gomock.Any(), gomock.Any(), gomock.Any()).
+ DoAndReturn(func(_ context.Context, _ string, body sdk.SSOAPIUpdateSSOConnectionJSONBody) (*http.Response, error) {
+ got, err := json.Marshal(body)
+ r.NoError(err)
+
+ expected := []byte(`{
+ "aad": {
+ "adDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ },
+ "name": "updated_name"
+}`)
+
+ eq, err := JSONBytesEqual(got, expected)
+ r.NoError(err)
+ r.True(eq, fmt.Sprintf("got: %v\n"+
+ "expected: %v\n", string(got), string(expected)))
+
+ returnBody := []byte(`{
+ "aad": {
+ "adDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ },
+ "status": "STATUS_ACTIVE",
+ "name": "updated_name"
+}`)
+
+ return &http.Response{
+ StatusCode: 200,
+ Header: map[string][]string{"Content-Type": {"json"}},
+ Body: io.NopCloser(bytes.NewReader(returnBody)),
+ }, nil
+ }).Times(1)
+
+ readBody := io.NopCloser(bytes.NewReader([]byte(`{
+ "id": "b6bfc074-a267-400f-b8f1-db0850c369b1",
+ "name": "updated_name",
+ "createdAt": "2023-11-02T10:49:14.376757Z",
+ "updatedAt": "2023-11-02T10:49:14.450828Z",
+ "emailDomain": "test_email",
+ "aad": {
+ "adDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ }
+}`)))
+ mockClient.EXPECT().
+ SSOAPIGetSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: readBody, Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ updateResult := resource.UpdateContext(ctx, data, provider)
+
+ r.Nil(updateResult)
+ r.False(updateResult.HasError())
+ r.Equal("updated_name", data.Get(FieldSSOConnectionName))
+ equalADConnector(t, r, data.Get(FieldSSOConnectionAAD), "updated_domain", "updated_client_id", "updated_client_secret")
+}
+
+func TestSSOConnection_UpdateOktaConnector(t *testing.T) {
+ r := require.New(t)
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ ctx := context.Background()
+ provider := &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ }
+ connectionID := "b6bfc074-a267-400f-b8f1-db0850c369b1"
+
+ raw := make(map[string]interface{})
+ raw[FieldSSOConnectionName] = "updated_name"
+
+ resource := resourceSSOConnection()
+ data := schema.TestResourceDataRaw(t, resource.Schema, raw)
+ data.SetId(connectionID)
+ r.NoError(data.Set(FieldSSOConnectionOkta, []map[string]interface{}{
+ {
+ FieldSSOConnectionOktaDomain: "updated_domain",
+ FieldSSOConnectionOktaClientID: "updated_client_id",
+ FieldSSOConnectionOktaClientSecret: "updated_client_secret",
+ },
+ }))
+
+ mockClient.EXPECT().SSOAPIUpdateSSOConnection(gomock.Any(), gomock.Any(), gomock.Any()).
+ DoAndReturn(func(_ context.Context, _ string, body sdk.SSOAPIUpdateSSOConnectionJSONBody) (*http.Response, error) {
+ got, err := json.Marshal(body)
+ r.NoError(err)
+
+ expected := []byte(`{
+ "okta": {
+ "oktaDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ },
+ "name": "updated_name"
+}`)
+
+ eq, err := JSONBytesEqual(got, expected)
+ r.NoError(err)
+ r.True(eq, fmt.Sprintf("got: %v\n"+
+ "expected: %v\n", string(got), string(expected)))
+
+ returnBody := []byte(`{
+ "okta": {
+ "oktaDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ },
+ "status": "STATUS_ACTIVE",
+ "name": "updated_name"
+}`)
+
+ return &http.Response{
+ StatusCode: 200,
+ Header: map[string][]string{"Content-Type": {"json"}},
+ Body: io.NopCloser(bytes.NewReader(returnBody)),
+ }, nil
+ }).Times(1)
+
+ readBody := io.NopCloser(bytes.NewReader([]byte(`{
+ "id": "b6bfc074-a267-400f-b8f1-db0850c369b1",
+ "name": "updated_name",
+ "createdAt": "2023-11-02T10:49:14.376757Z",
+ "updatedAt": "2023-11-02T10:49:14.450828Z",
+ "emailDomain": "test_email",
+ "okta": {
+ "oktaDomain": "updated_domain",
+ "clientId": "updated_client_id",
+ "clientSecret": "updated_client_secret"
+ }
+}`)))
+ mockClient.EXPECT().
+ SSOAPIGetSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: readBody, Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ updateResult := resource.UpdateContext(ctx, data, provider)
+ r.Nil(updateResult)
+ r.False(updateResult.HasError())
+ r.Equal("updated_name", data.Get(FieldSSOConnectionName))
+ equalOktaConnector(t, r, data.Get(FieldSSOConnectionOkta), "updated_domain", "updated_client_id", "updated_client_secret")
+}
+
+func TestSSOConnection_DeleteContext(t *testing.T) {
+ r := require.New(t)
+ mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))
+
+ provider := &ProviderConfig{
+ api: &sdk.ClientWithResponses{
+ ClientInterface: mockClient,
+ },
+ }
+
+ connectionID := "b6bfc074-a267-400f-b8f1-db0850c369b1"
+
+ resource := resourceSSOConnection()
+ data := resource.Data(
+ terraform.NewInstanceStateShimmedFromValue(
+ cty.ObjectVal(map[string]cty.Value{
+ "id": cty.StringVal(connectionID),
+ }), 0),
+ )
+
+ mockClient.EXPECT().
+ SSOAPIDeleteSSOConnection(gomock.Any(), connectionID).
+ Return(&http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader([]byte(`{}`))), Header: map[string][]string{"Content-Type": {"json"}}}, nil)
+
+ ctx := context.Background()
+ result := resource.DeleteContext(ctx, data, provider)
+ r.Nil(result)
+ r.False(result.HasError())
+ r.Empty(data.Get(FieldSSOConnectionOkta))
+ r.Empty(data.Get(FieldSSOConnectionAAD))
+ r.Empty(data.Get(FieldSSOConnectionName))
+ r.Empty(data.Get(FieldSSOConnectionEmailDomain))
+}
+
+func testAccCreateSSOConnectionConfig(rName, clientID, clientSecret, adDomain string) string {
+ return fmt.Sprintf(`
+resource "castai_sso_connection" "test" {
+ name = %[1]q
+ email_domain = "aad_connection@test.com"
+ aad {
+ client_id = %[2]q
+ client_secret = %[3]q
+ ad_domain = %[4]q
+ }
+}`, rName, clientID, clientSecret, adDomain)
+}
+
+func testAccSSOConnectionConfigurationDestroy(s *terraform.State) error {
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ client := testAccProvider.Meta().(*ProviderConfig).api
+ for _, rs := range s.RootModule().Resources {
+ if rs.Type != "castai_sso_connection" {
+ continue
+ }
+
+ response, err := client.SSOAPIGetSSOConnectionWithResponse(ctx, rs.Primary.ID)
+ if err != nil {
+ return err
+ }
+
+ if response.StatusCode() == http.StatusNotFound {
+ return nil
+ }
+
+ return fmt.Errorf("sso connection %s still exists", rs.Primary.ID)
+ }
+
+ return nil
+}
+
+func equalOktaConnector(t *testing.T, r *require.Assertions, in interface{}, expectedDomain, expectedClientID, expectedClientSecret string) {
+ t.Helper()
+ r.NotNil(in)
+
+ array, ok := in.([]interface{})
+ r.True(ok)
+ r.Len(array, 1)
+ values, ok := array[0].(map[string]interface{})
+ r.True(ok)
+
+ domain, ok := values["okta_domain"]
+ r.True(ok)
+ r.Equal(expectedDomain, domain)
+ clientID, ok := values["client_id"]
+ r.True(ok)
+ r.Equal(expectedClientID, clientID)
+ clientSecret, ok := values["client_secret"]
+ r.True(ok)
+ r.Equal(expectedClientSecret, clientSecret)
+}
+
+func equalADConnector(t *testing.T, r *require.Assertions, in interface{}, expectedDomain, expectedClientID, expectedClientSecret string) {
+ t.Helper()
+ r.NotNil(in)
+
+ array, ok := in.([]interface{})
+ r.True(ok)
+ r.Len(array, 1)
+ values, ok := array[0].(map[string]interface{})
+ r.True(ok)
+
+ domain, ok := values["ad_domain"]
+ r.True(ok)
+ r.Equal(expectedDomain, domain)
+ clientID, ok := values["client_id"]
+ r.True(ok)
+ r.Equal(expectedClientID, clientID)
+ clientSecret, ok := values["client_secret"]
+ r.True(ok)
+ r.Equal(expectedClientSecret, clientSecret)
+}
diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go
index 421eeaea..f67c9075 100644
--- a/castai/sdk/api.gen.go
+++ b/castai/sdk/api.gen.go
@@ -60,6 +60,14 @@ const (
CastaiInventoryV1beta1StorageInfoDeviceTypeSsd CastaiInventoryV1beta1StorageInfoDeviceType = "ssd"
)
+// Defines values for CastaiSsoV1beta1SSOConnectionStatus.
+const (
+ STATUSACTIVE CastaiSsoV1beta1SSOConnectionStatus = "STATUS_ACTIVE"
+ STATUSFAILED CastaiSsoV1beta1SSOConnectionStatus = "STATUS_FAILED"
+ STATUSINACTIVE CastaiSsoV1beta1SSOConnectionStatus = "STATUS_INACTIVE"
+ STATUSUNKNOWN CastaiSsoV1beta1SSOConnectionStatus = "STATUS_UNKNOWN"
+)
+
// Defines values for CastaiV1Cloud.
const (
CastaiV1CloudAWS CastaiV1Cloud = "AWS"
@@ -639,6 +647,111 @@ type CastaiOperationsV1beta1OperationError struct {
Reason *string `json:"reason,omitempty"`
}
+// AzureAAD represents a Azure AAD connector.
+type CastaiSsoV1beta1AzureAAD struct {
+ // ADDomain is the domain of the Azure AD.
+ AdDomain string `json:"adDomain"`
+
+ // ClientId is the client id of the Azure AD.
+ ClientId string `json:"clientId"`
+
+ // ClientSecret is the client secret of the Azure AD.
+ ClientSecret *string `json:"clientSecret,omitempty"`
+}
+
+// CreateSSOConnection represents a sso connection creation request.
+type CastaiSsoV1beta1CreateSSOConnection struct {
+ // AzureAAD represents a Azure AAD connector.
+ Aad *CastaiSsoV1beta1AzureAAD `json:"aad,omitempty"`
+
+ // EmailDomain is the email domain of the connection.
+ EmailDomain string `json:"emailDomain"`
+
+ // Name is the name of the connection.
+ Name string `json:"name"`
+
+ // Okta represents a Okta connector.
+ Okta *CastaiSsoV1beta1Okta `json:"okta,omitempty"`
+}
+
+// Defines the container for the sso delete response.
+type CastaiSsoV1beta1DeleteSSOConnectionResponse = map[string]interface{}
+
+// Defines the container for the sso list response.
+type CastaiSsoV1beta1ListSSOConnectionsResponse struct {
+ Connections []CastaiSsoV1beta1SSOConnection `json:"connections"`
+}
+
+// Okta represents a Okta connector.
+type CastaiSsoV1beta1Okta struct {
+ // ClientId is the client id of the Okta.
+ ClientId string `json:"clientId"`
+
+ // ClientSecret is the client secret of the Okta.
+ ClientSecret *string `json:"clientSecret,omitempty"`
+
+ // OktaDomain is the domain of the Okta.
+ OktaDomain string `json:"oktaDomain"`
+}
+
+// SSOConnection represents a sso connection.
+type CastaiSsoV1beta1SSOConnection struct {
+ // AzureAAD represents a Azure AAD connector.
+ Aad *CastaiSsoV1beta1AzureAAD `json:"aad,omitempty"`
+
+ // CreatedAt is the time when the connection was created.
+ CreatedAt *time.Time `json:"createdAt,omitempty"`
+
+ // EmailDomain is the email domain of the connection.
+ EmailDomain string `json:"emailDomain"`
+
+ // Error is the error message of the connection.
+ Error *string `json:"error,omitempty"`
+
+ // Id is the unique identifier of the connection.
+ Id *string `json:"id,omitempty"`
+
+ // Name is the name of the connection.
+ Name string `json:"name"`
+
+ // Okta represents a Okta connector.
+ Okta *CastaiSsoV1beta1Okta `json:"okta,omitempty"`
+
+ // Status is the status of the connection.
+ //
+ // - STATUS_UNKNOWN: StatusUnknown is the default status.
+ // - STATUS_ACTIVE: StatusActive is the active status.
+ // - STATUS_INACTIVE: StatusInactive is the inactive status.
+ // - STATUS_FAILED: StatusFailed is the failed status.
+ Status *CastaiSsoV1beta1SSOConnectionStatus `json:"status,omitempty"`
+
+ // UpdatedAt is the time when the connection was last updated.
+ UpdatedAt *time.Time `json:"updatedAt,omitempty"`
+}
+
+// Status is the status of the connection.
+//
+// - STATUS_UNKNOWN: StatusUnknown is the default status.
+// - STATUS_ACTIVE: StatusActive is the active status.
+// - STATUS_INACTIVE: StatusInactive is the inactive status.
+// - STATUS_FAILED: StatusFailed is the failed status.
+type CastaiSsoV1beta1SSOConnectionStatus string
+
+// SSOConnection represents a sso connection.
+type CastaiSsoV1beta1UpdateSSOConnection struct {
+ // AzureAAD represents a Azure AAD connector.
+ Aad *CastaiSsoV1beta1AzureAAD `json:"aad,omitempty"`
+
+ // EmailDomain is the email domain of the connection.
+ EmailDomain *string `json:"emailDomain,omitempty"`
+
+ // Name is the name of the connection.
+ Name *string `json:"name,omitempty"`
+
+ // Okta represents a Okta connector.
+ Okta *CastaiSsoV1beta1Okta `json:"okta,omitempty"`
+}
+
// Types of cloud service providers CAST AI supports.
//
// - invalid: Invalid.
@@ -2245,6 +2358,12 @@ type ExternalClusterAPIGetCredentialsScriptTemplateParams struct {
CrossRole *bool `form:"crossRole,omitempty" json:"crossRole,omitempty"`
}
+// SSOAPICreateSSOConnectionJSONBody defines parameters for SSOAPICreateSSOConnection.
+type SSOAPICreateSSOConnectionJSONBody = CastaiSsoV1beta1CreateSSOConnection
+
+// SSOAPIUpdateSSOConnectionJSONBody defines parameters for SSOAPIUpdateSSOConnection.
+type SSOAPIUpdateSSOConnectionJSONBody = CastaiSsoV1beta1UpdateSSOConnection
+
// AuthTokenAPICreateAuthTokenJSONRequestBody defines body for AuthTokenAPICreateAuthToken for application/json ContentType.
type AuthTokenAPICreateAuthTokenJSONRequestBody = AuthTokenAPICreateAuthTokenJSONBody
@@ -2332,6 +2451,12 @@ type ScheduledRebalancingAPICreateRebalancingScheduleJSONRequestBody = Scheduled
// ScheduledRebalancingAPIUpdateRebalancingScheduleJSONRequestBody defines body for ScheduledRebalancingAPIUpdateRebalancingSchedule for application/json ContentType.
type ScheduledRebalancingAPIUpdateRebalancingScheduleJSONRequestBody = ScheduledRebalancingAPIUpdateRebalancingScheduleJSONBody
+// SSOAPICreateSSOConnectionJSONRequestBody defines body for SSOAPICreateSSOConnection for application/json ContentType.
+type SSOAPICreateSSOConnectionJSONRequestBody = SSOAPICreateSSOConnectionJSONBody
+
+// SSOAPIUpdateSSOConnectionJSONRequestBody defines body for SSOAPIUpdateSSOConnection for application/json ContentType.
+type SSOAPIUpdateSSOConnectionJSONRequestBody = SSOAPIUpdateSSOConnectionJSONBody
+
// Getter for additional properties for CastaiEvictorV1LabelSelector_MatchLabels. Returns the specified
// element and whether it was found
func (a CastaiEvictorV1LabelSelector_MatchLabels) Get(fieldName string) (value string, found bool) {
diff --git a/castai/sdk/client.gen.go b/castai/sdk/client.gen.go
index d936d843..d4c6a844 100644
--- a/castai/sdk/client.gen.go
+++ b/castai/sdk/client.gen.go
@@ -382,6 +382,25 @@ type ClientInterface interface {
// ExternalClusterAPIGetCredentialsScriptTemplate request
ExternalClusterAPIGetCredentialsScriptTemplate(ctx context.Context, provider string, params *ExternalClusterAPIGetCredentialsScriptTemplateParams, reqEditors ...RequestEditorFn) (*http.Response, error)
+ // SSOAPIListSSOConnections request
+ SSOAPIListSSOConnections(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // SSOAPICreateSSOConnection request with any body
+ SSOAPICreateSSOConnectionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ SSOAPICreateSSOConnection(ctx context.Context, body SSOAPICreateSSOConnectionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // SSOAPIDeleteSSOConnection request
+ SSOAPIDeleteSSOConnection(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // SSOAPIGetSSOConnection request
+ SSOAPIGetSSOConnection(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // SSOAPIUpdateSSOConnection request with any body
+ SSOAPIUpdateSSOConnectionWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ SSOAPIUpdateSSOConnection(ctx context.Context, id string, body SSOAPIUpdateSSOConnectionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
// ScheduledRebalancingAPIListAvailableRebalancingTZ request
ScheduledRebalancingAPIListAvailableRebalancingTZ(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
}
@@ -1670,6 +1689,90 @@ func (c *Client) ExternalClusterAPIGetCredentialsScriptTemplate(ctx context.Cont
return c.Client.Do(req)
}
+func (c *Client) SSOAPIListSSOConnections(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPIListSSOConnectionsRequest(c.Server)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPICreateSSOConnectionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPICreateSSOConnectionRequestWithBody(c.Server, contentType, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPICreateSSOConnection(ctx context.Context, body SSOAPICreateSSOConnectionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPICreateSSOConnectionRequest(c.Server, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPIDeleteSSOConnection(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPIDeleteSSOConnectionRequest(c.Server, id)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPIGetSSOConnection(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPIGetSSOConnectionRequest(c.Server, id)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPIUpdateSSOConnectionWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPIUpdateSSOConnectionRequestWithBody(c.Server, id, contentType, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) SSOAPIUpdateSSOConnection(ctx context.Context, id string, body SSOAPIUpdateSSOConnectionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewSSOAPIUpdateSSOConnectionRequest(c.Server, id, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
func (c *Client) ScheduledRebalancingAPIListAvailableRebalancingTZ(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
req, err := NewScheduledRebalancingAPIListAvailableRebalancingTZRequest(c.Server)
if err != nil {
@@ -4992,6 +5095,188 @@ func NewExternalClusterAPIGetCredentialsScriptTemplateRequest(server string, pro
return req, nil
}
+// NewSSOAPIListSSOConnectionsRequest generates requests for SSOAPIListSSOConnections
+func NewSSOAPIListSSOConnectionsRequest(server string) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/v1/sso-connections")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("GET", queryURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return req, nil
+}
+
+// NewSSOAPICreateSSOConnectionRequest calls the generic SSOAPICreateSSOConnection builder with application/json body
+func NewSSOAPICreateSSOConnectionRequest(server string, body SSOAPICreateSSOConnectionJSONRequestBody) (*http.Request, error) {
+ var bodyReader io.Reader
+ buf, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader = bytes.NewReader(buf)
+ return NewSSOAPICreateSSOConnectionRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewSSOAPICreateSSOConnectionRequestWithBody generates requests for SSOAPICreateSSOConnection with any type of body
+func NewSSOAPICreateSSOConnectionRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/v1/sso-connections")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", queryURL.String(), body)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Add("Content-Type", contentType)
+
+ return req, nil
+}
+
+// NewSSOAPIDeleteSSOConnectionRequest generates requests for SSOAPIDeleteSSOConnection
+func NewSSOAPIDeleteSSOConnectionRequest(server string, id string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "id", runtime.ParamLocationPath, id)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/v1/sso-connections/%s", pathParam0)
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("DELETE", queryURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return req, nil
+}
+
+// NewSSOAPIGetSSOConnectionRequest generates requests for SSOAPIGetSSOConnection
+func NewSSOAPIGetSSOConnectionRequest(server string, id string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "id", runtime.ParamLocationPath, id)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/v1/sso-connections/%s", pathParam0)
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("GET", queryURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return req, nil
+}
+
+// NewSSOAPIUpdateSSOConnectionRequest calls the generic SSOAPIUpdateSSOConnection builder with application/json body
+func NewSSOAPIUpdateSSOConnectionRequest(server string, id string, body SSOAPIUpdateSSOConnectionJSONRequestBody) (*http.Request, error) {
+ var bodyReader io.Reader
+ buf, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader = bytes.NewReader(buf)
+ return NewSSOAPIUpdateSSOConnectionRequestWithBody(server, id, "application/json", bodyReader)
+}
+
+// NewSSOAPIUpdateSSOConnectionRequestWithBody generates requests for SSOAPIUpdateSSOConnection with any type of body
+func NewSSOAPIUpdateSSOConnectionRequestWithBody(server string, id string, contentType string, body io.Reader) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "id", runtime.ParamLocationPath, id)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/v1/sso-connections/%s", pathParam0)
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", queryURL.String(), body)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Add("Content-Type", contentType)
+
+ return req, nil
+}
+
// NewScheduledRebalancingAPIListAvailableRebalancingTZRequest generates requests for ScheduledRebalancingAPIListAvailableRebalancingTZ
func NewScheduledRebalancingAPIListAvailableRebalancingTZRequest(server string) (*http.Request, error) {
var err error
@@ -5354,6 +5639,25 @@ type ClientWithResponsesInterface interface {
// ExternalClusterAPIGetCredentialsScriptTemplate request
ExternalClusterAPIGetCredentialsScriptTemplateWithResponse(ctx context.Context, provider string, params *ExternalClusterAPIGetCredentialsScriptTemplateParams) (*ExternalClusterAPIGetCredentialsScriptTemplateResponse, error)
+ // SSOAPIListSSOConnections request
+ SSOAPIListSSOConnectionsWithResponse(ctx context.Context) (*SSOAPIListSSOConnectionsResponse, error)
+
+ // SSOAPICreateSSOConnection request with any body
+ SSOAPICreateSSOConnectionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*SSOAPICreateSSOConnectionResponse, error)
+
+ SSOAPICreateSSOConnectionWithResponse(ctx context.Context, body SSOAPICreateSSOConnectionJSONRequestBody) (*SSOAPICreateSSOConnectionResponse, error)
+
+ // SSOAPIDeleteSSOConnection request
+ SSOAPIDeleteSSOConnectionWithResponse(ctx context.Context, id string) (*SSOAPIDeleteSSOConnectionResponse, error)
+
+ // SSOAPIGetSSOConnection request
+ SSOAPIGetSSOConnectionWithResponse(ctx context.Context, id string) (*SSOAPIGetSSOConnectionResponse, error)
+
+ // SSOAPIUpdateSSOConnection request with any body
+ SSOAPIUpdateSSOConnectionWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader) (*SSOAPIUpdateSSOConnectionResponse, error)
+
+ SSOAPIUpdateSSOConnectionWithResponse(ctx context.Context, id string, body SSOAPIUpdateSSOConnectionJSONRequestBody) (*SSOAPIUpdateSSOConnectionResponse, error)
+
// ScheduledRebalancingAPIListAvailableRebalancingTZ request
ScheduledRebalancingAPIListAvailableRebalancingTZWithResponse(ctx context.Context) (*ScheduledRebalancingAPIListAvailableRebalancingTZResponse, error)
}
@@ -7704,14 +8008,14 @@ func (r ExternalClusterAPIGetCredentialsScriptTemplateResponse) GetBody() []byte
// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
-type ScheduledRebalancingAPIListAvailableRebalancingTZResponse struct {
+type SSOAPIListSSOConnectionsResponse struct {
Body []byte
HTTPResponse *http.Response
- JSON200 *ScheduledrebalancingV1ListAvailableRebalancingTZResponse
+ JSON200 *CastaiSsoV1beta1ListSSOConnectionsResponse
}
// Status returns HTTPResponse.Status
-func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) Status() string {
+func (r SSOAPIListSSOConnectionsResponse) Status() string {
if r.HTTPResponse != nil {
return r.HTTPResponse.Status
}
@@ -7719,7 +8023,7 @@ func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) Status() stri
}
// StatusCode returns HTTPResponse.StatusCode
-func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) StatusCode() int {
+func (r SSOAPIListSSOConnectionsResponse) StatusCode() int {
if r.HTTPResponse != nil {
return r.HTTPResponse.StatusCode
}
@@ -7728,18 +8032,168 @@ func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) StatusCode()
// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
// Body returns body of byte array
-func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) GetBody() []byte {
+func (r SSOAPIListSSOConnectionsResponse) GetBody() []byte {
return r.Body
}
// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
-// AuthTokenAPIListAuthTokensWithResponse request returning *AuthTokenAPIListAuthTokensResponse
-func (c *ClientWithResponses) AuthTokenAPIListAuthTokensWithResponse(ctx context.Context, params *AuthTokenAPIListAuthTokensParams) (*AuthTokenAPIListAuthTokensResponse, error) {
- rsp, err := c.AuthTokenAPIListAuthTokens(ctx, params)
- if err != nil {
- return nil, err
- }
+type SSOAPICreateSSOConnectionResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *CastaiSsoV1beta1SSOConnection
+}
+
+// Status returns HTTPResponse.Status
+func (r SSOAPICreateSSOConnectionResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r SSOAPICreateSSOConnectionResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+// Body returns body of byte array
+func (r SSOAPICreateSSOConnectionResponse) GetBody() []byte {
+ return r.Body
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+
+type SSOAPIDeleteSSOConnectionResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *CastaiSsoV1beta1DeleteSSOConnectionResponse
+}
+
+// Status returns HTTPResponse.Status
+func (r SSOAPIDeleteSSOConnectionResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r SSOAPIDeleteSSOConnectionResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+// Body returns body of byte array
+func (r SSOAPIDeleteSSOConnectionResponse) GetBody() []byte {
+ return r.Body
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+
+type SSOAPIGetSSOConnectionResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *CastaiSsoV1beta1SSOConnection
+}
+
+// Status returns HTTPResponse.Status
+func (r SSOAPIGetSSOConnectionResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r SSOAPIGetSSOConnectionResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+// Body returns body of byte array
+func (r SSOAPIGetSSOConnectionResponse) GetBody() []byte {
+ return r.Body
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+
+type SSOAPIUpdateSSOConnectionResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *CastaiSsoV1beta1SSOConnection
+}
+
+// Status returns HTTPResponse.Status
+func (r SSOAPIUpdateSSOConnectionResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r SSOAPIUpdateSSOConnectionResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+// Body returns body of byte array
+func (r SSOAPIUpdateSSOConnectionResponse) GetBody() []byte {
+ return r.Body
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+
+type ScheduledRebalancingAPIListAvailableRebalancingTZResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *ScheduledrebalancingV1ListAvailableRebalancingTZResponse
+}
+
+// Status returns HTTPResponse.Status
+func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+// Body returns body of byte array
+func (r ScheduledRebalancingAPIListAvailableRebalancingTZResponse) GetBody() []byte {
+ return r.Body
+}
+
+// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240
+
+// AuthTokenAPIListAuthTokensWithResponse request returning *AuthTokenAPIListAuthTokensResponse
+func (c *ClientWithResponses) AuthTokenAPIListAuthTokensWithResponse(ctx context.Context, params *AuthTokenAPIListAuthTokensParams) (*AuthTokenAPIListAuthTokensResponse, error) {
+ rsp, err := c.AuthTokenAPIListAuthTokens(ctx, params)
+ if err != nil {
+ return nil, err
+ }
return ParseAuthTokenAPIListAuthTokensResponse(rsp)
}
@@ -8668,6 +9122,67 @@ func (c *ClientWithResponses) ExternalClusterAPIGetCredentialsScriptTemplateWith
return ParseExternalClusterAPIGetCredentialsScriptTemplateResponse(rsp)
}
+// SSOAPIListSSOConnectionsWithResponse request returning *SSOAPIListSSOConnectionsResponse
+func (c *ClientWithResponses) SSOAPIListSSOConnectionsWithResponse(ctx context.Context) (*SSOAPIListSSOConnectionsResponse, error) {
+ rsp, err := c.SSOAPIListSSOConnections(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPIListSSOConnectionsResponse(rsp)
+}
+
+// SSOAPICreateSSOConnectionWithBodyWithResponse request with arbitrary body returning *SSOAPICreateSSOConnectionResponse
+func (c *ClientWithResponses) SSOAPICreateSSOConnectionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*SSOAPICreateSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPICreateSSOConnectionWithBody(ctx, contentType, body)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPICreateSSOConnectionResponse(rsp)
+}
+
+func (c *ClientWithResponses) SSOAPICreateSSOConnectionWithResponse(ctx context.Context, body SSOAPICreateSSOConnectionJSONRequestBody) (*SSOAPICreateSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPICreateSSOConnection(ctx, body)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPICreateSSOConnectionResponse(rsp)
+}
+
+// SSOAPIDeleteSSOConnectionWithResponse request returning *SSOAPIDeleteSSOConnectionResponse
+func (c *ClientWithResponses) SSOAPIDeleteSSOConnectionWithResponse(ctx context.Context, id string) (*SSOAPIDeleteSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPIDeleteSSOConnection(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPIDeleteSSOConnectionResponse(rsp)
+}
+
+// SSOAPIGetSSOConnectionWithResponse request returning *SSOAPIGetSSOConnectionResponse
+func (c *ClientWithResponses) SSOAPIGetSSOConnectionWithResponse(ctx context.Context, id string) (*SSOAPIGetSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPIGetSSOConnection(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPIGetSSOConnectionResponse(rsp)
+}
+
+// SSOAPIUpdateSSOConnectionWithBodyWithResponse request with arbitrary body returning *SSOAPIUpdateSSOConnectionResponse
+func (c *ClientWithResponses) SSOAPIUpdateSSOConnectionWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader) (*SSOAPIUpdateSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPIUpdateSSOConnectionWithBody(ctx, id, contentType, body)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPIUpdateSSOConnectionResponse(rsp)
+}
+
+func (c *ClientWithResponses) SSOAPIUpdateSSOConnectionWithResponse(ctx context.Context, id string, body SSOAPIUpdateSSOConnectionJSONRequestBody) (*SSOAPIUpdateSSOConnectionResponse, error) {
+ rsp, err := c.SSOAPIUpdateSSOConnection(ctx, id, body)
+ if err != nil {
+ return nil, err
+ }
+ return ParseSSOAPIUpdateSSOConnectionResponse(rsp)
+}
+
// ScheduledRebalancingAPIListAvailableRebalancingTZWithResponse request returning *ScheduledRebalancingAPIListAvailableRebalancingTZResponse
func (c *ClientWithResponses) ScheduledRebalancingAPIListAvailableRebalancingTZWithResponse(ctx context.Context) (*ScheduledRebalancingAPIListAvailableRebalancingTZResponse, error) {
rsp, err := c.ScheduledRebalancingAPIListAvailableRebalancingTZ(ctx)
@@ -10675,6 +11190,136 @@ func ParseExternalClusterAPIGetCredentialsScriptTemplateResponse(rsp *http.Respo
return response, nil
}
+// ParseSSOAPIListSSOConnectionsResponse parses an HTTP response from a SSOAPIListSSOConnectionsWithResponse call
+func ParseSSOAPIListSSOConnectionsResponse(rsp *http.Response) (*SSOAPIListSSOConnectionsResponse, error) {
+ bodyBytes, err := ioutil.ReadAll(rsp.Body)
+ defer rsp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &SSOAPIListSSOConnectionsResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest CastaiSsoV1beta1ListSSOConnectionsResponse
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseSSOAPICreateSSOConnectionResponse parses an HTTP response from a SSOAPICreateSSOConnectionWithResponse call
+func ParseSSOAPICreateSSOConnectionResponse(rsp *http.Response) (*SSOAPICreateSSOConnectionResponse, error) {
+ bodyBytes, err := ioutil.ReadAll(rsp.Body)
+ defer rsp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &SSOAPICreateSSOConnectionResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest CastaiSsoV1beta1SSOConnection
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseSSOAPIDeleteSSOConnectionResponse parses an HTTP response from a SSOAPIDeleteSSOConnectionWithResponse call
+func ParseSSOAPIDeleteSSOConnectionResponse(rsp *http.Response) (*SSOAPIDeleteSSOConnectionResponse, error) {
+ bodyBytes, err := ioutil.ReadAll(rsp.Body)
+ defer rsp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &SSOAPIDeleteSSOConnectionResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest CastaiSsoV1beta1DeleteSSOConnectionResponse
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseSSOAPIGetSSOConnectionResponse parses an HTTP response from a SSOAPIGetSSOConnectionWithResponse call
+func ParseSSOAPIGetSSOConnectionResponse(rsp *http.Response) (*SSOAPIGetSSOConnectionResponse, error) {
+ bodyBytes, err := ioutil.ReadAll(rsp.Body)
+ defer rsp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &SSOAPIGetSSOConnectionResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest CastaiSsoV1beta1SSOConnection
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseSSOAPIUpdateSSOConnectionResponse parses an HTTP response from a SSOAPIUpdateSSOConnectionWithResponse call
+func ParseSSOAPIUpdateSSOConnectionResponse(rsp *http.Response) (*SSOAPIUpdateSSOConnectionResponse, error) {
+ bodyBytes, err := ioutil.ReadAll(rsp.Body)
+ defer rsp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &SSOAPIUpdateSSOConnectionResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest CastaiSsoV1beta1SSOConnection
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
// ParseScheduledRebalancingAPIListAvailableRebalancingTZResponse parses an HTTP response from a ScheduledRebalancingAPIListAvailableRebalancingTZWithResponse call
func ParseScheduledRebalancingAPIListAvailableRebalancingTZResponse(rsp *http.Response) (*ScheduledRebalancingAPIListAvailableRebalancingTZResponse, error) {
bodyBytes, err := ioutil.ReadAll(rsp.Body)
diff --git a/castai/sdk/mock/client.go b/castai/sdk/mock/client.go
index 73d2782a..9d7f291c 100644
--- a/castai/sdk/mock/client.go
+++ b/castai/sdk/mock/client.go
@@ -1775,6 +1775,146 @@ func (mr *MockClientInterfaceMockRecorder) PoliciesAPIUpsertClusterPoliciesWithB
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PoliciesAPIUpsertClusterPoliciesWithBody", reflect.TypeOf((*MockClientInterface)(nil).PoliciesAPIUpsertClusterPoliciesWithBody), varargs...)
}
+// SSOAPICreateSSOConnection mocks base method.
+func (m *MockClientInterface) SSOAPICreateSSOConnection(ctx context.Context, body sdk.SSOAPICreateSSOConnectionJSONRequestBody, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, body}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPICreateSSOConnection", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPICreateSSOConnection indicates an expected call of SSOAPICreateSSOConnection.
+func (mr *MockClientInterfaceMockRecorder) SSOAPICreateSSOConnection(ctx, body interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, body}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPICreateSSOConnection", reflect.TypeOf((*MockClientInterface)(nil).SSOAPICreateSSOConnection), varargs...)
+}
+
+// SSOAPICreateSSOConnectionWithBody mocks base method.
+func (m *MockClientInterface) SSOAPICreateSSOConnectionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, contentType, body}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPICreateSSOConnectionWithBody", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPICreateSSOConnectionWithBody indicates an expected call of SSOAPICreateSSOConnectionWithBody.
+func (mr *MockClientInterfaceMockRecorder) SSOAPICreateSSOConnectionWithBody(ctx, contentType, body interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, contentType, body}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPICreateSSOConnectionWithBody", reflect.TypeOf((*MockClientInterface)(nil).SSOAPICreateSSOConnectionWithBody), varargs...)
+}
+
+// SSOAPIDeleteSSOConnection mocks base method.
+func (m *MockClientInterface) SSOAPIDeleteSSOConnection(ctx context.Context, id string, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, id}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPIDeleteSSOConnection", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIDeleteSSOConnection indicates an expected call of SSOAPIDeleteSSOConnection.
+func (mr *MockClientInterfaceMockRecorder) SSOAPIDeleteSSOConnection(ctx, id interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, id}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIDeleteSSOConnection", reflect.TypeOf((*MockClientInterface)(nil).SSOAPIDeleteSSOConnection), varargs...)
+}
+
+// SSOAPIGetSSOConnection mocks base method.
+func (m *MockClientInterface) SSOAPIGetSSOConnection(ctx context.Context, id string, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, id}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPIGetSSOConnection", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIGetSSOConnection indicates an expected call of SSOAPIGetSSOConnection.
+func (mr *MockClientInterfaceMockRecorder) SSOAPIGetSSOConnection(ctx, id interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, id}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIGetSSOConnection", reflect.TypeOf((*MockClientInterface)(nil).SSOAPIGetSSOConnection), varargs...)
+}
+
+// SSOAPIListSSOConnections mocks base method.
+func (m *MockClientInterface) SSOAPIListSSOConnections(ctx context.Context, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPIListSSOConnections", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIListSSOConnections indicates an expected call of SSOAPIListSSOConnections.
+func (mr *MockClientInterfaceMockRecorder) SSOAPIListSSOConnections(ctx interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIListSSOConnections", reflect.TypeOf((*MockClientInterface)(nil).SSOAPIListSSOConnections), varargs...)
+}
+
+// SSOAPIUpdateSSOConnection mocks base method.
+func (m *MockClientInterface) SSOAPIUpdateSSOConnection(ctx context.Context, id string, body sdk.SSOAPIUpdateSSOConnectionJSONRequestBody, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, id, body}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPIUpdateSSOConnection", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIUpdateSSOConnection indicates an expected call of SSOAPIUpdateSSOConnection.
+func (mr *MockClientInterfaceMockRecorder) SSOAPIUpdateSSOConnection(ctx, id, body interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, id, body}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIUpdateSSOConnection", reflect.TypeOf((*MockClientInterface)(nil).SSOAPIUpdateSSOConnection), varargs...)
+}
+
+// SSOAPIUpdateSSOConnectionWithBody mocks base method.
+func (m *MockClientInterface) SSOAPIUpdateSSOConnectionWithBody(ctx context.Context, id, contentType string, body io.Reader, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{ctx, id, contentType, body}
+ for _, a := range reqEditors {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "SSOAPIUpdateSSOConnectionWithBody", varargs...)
+ ret0, _ := ret[0].(*http.Response)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIUpdateSSOConnectionWithBody indicates an expected call of SSOAPIUpdateSSOConnectionWithBody.
+func (mr *MockClientInterfaceMockRecorder) SSOAPIUpdateSSOConnectionWithBody(ctx, id, contentType, body interface{}, reqEditors ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{ctx, id, contentType, body}, reqEditors...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIUpdateSSOConnectionWithBody", reflect.TypeOf((*MockClientInterface)(nil).SSOAPIUpdateSSOConnectionWithBody), varargs...)
+}
+
// ScheduledRebalancingAPICreateRebalancingJob mocks base method.
func (m *MockClientInterface) ScheduledRebalancingAPICreateRebalancingJob(ctx context.Context, clusterId string, body sdk.ScheduledRebalancingAPICreateRebalancingJobJSONRequestBody, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) {
m.ctrl.T.Helper()
@@ -3533,6 +3673,111 @@ func (mr *MockClientWithResponsesInterfaceMockRecorder) PoliciesAPIUpsertCluster
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PoliciesAPIUpsertClusterPoliciesWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).PoliciesAPIUpsertClusterPoliciesWithResponse), ctx, clusterId, body)
}
+// SSOAPICreateSSOConnectionWithBodyWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPICreateSSOConnectionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*sdk.SSOAPICreateSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPICreateSSOConnectionWithBodyWithResponse", ctx, contentType, body)
+ ret0, _ := ret[0].(*sdk.SSOAPICreateSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPICreateSSOConnectionWithBodyWithResponse indicates an expected call of SSOAPICreateSSOConnectionWithBodyWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPICreateSSOConnectionWithBodyWithResponse(ctx, contentType, body interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPICreateSSOConnectionWithBodyWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPICreateSSOConnectionWithBodyWithResponse), ctx, contentType, body)
+}
+
+// SSOAPICreateSSOConnectionWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPICreateSSOConnectionWithResponse(ctx context.Context, body sdk.SSOAPICreateSSOConnectionJSONRequestBody) (*sdk.SSOAPICreateSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPICreateSSOConnectionWithResponse", ctx, body)
+ ret0, _ := ret[0].(*sdk.SSOAPICreateSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPICreateSSOConnectionWithResponse indicates an expected call of SSOAPICreateSSOConnectionWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPICreateSSOConnectionWithResponse(ctx, body interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPICreateSSOConnectionWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPICreateSSOConnectionWithResponse), ctx, body)
+}
+
+// SSOAPIDeleteSSOConnectionWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPIDeleteSSOConnectionWithResponse(ctx context.Context, id string) (*sdk.SSOAPIDeleteSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPIDeleteSSOConnectionWithResponse", ctx, id)
+ ret0, _ := ret[0].(*sdk.SSOAPIDeleteSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIDeleteSSOConnectionWithResponse indicates an expected call of SSOAPIDeleteSSOConnectionWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPIDeleteSSOConnectionWithResponse(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIDeleteSSOConnectionWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPIDeleteSSOConnectionWithResponse), ctx, id)
+}
+
+// SSOAPIGetSSOConnectionWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPIGetSSOConnectionWithResponse(ctx context.Context, id string) (*sdk.SSOAPIGetSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPIGetSSOConnectionWithResponse", ctx, id)
+ ret0, _ := ret[0].(*sdk.SSOAPIGetSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIGetSSOConnectionWithResponse indicates an expected call of SSOAPIGetSSOConnectionWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPIGetSSOConnectionWithResponse(ctx, id interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIGetSSOConnectionWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPIGetSSOConnectionWithResponse), ctx, id)
+}
+
+// SSOAPIListSSOConnectionsWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPIListSSOConnectionsWithResponse(ctx context.Context) (*sdk.SSOAPIListSSOConnectionsResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPIListSSOConnectionsWithResponse", ctx)
+ ret0, _ := ret[0].(*sdk.SSOAPIListSSOConnectionsResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIListSSOConnectionsWithResponse indicates an expected call of SSOAPIListSSOConnectionsWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPIListSSOConnectionsWithResponse(ctx interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIListSSOConnectionsWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPIListSSOConnectionsWithResponse), ctx)
+}
+
+// SSOAPIUpdateSSOConnectionWithBodyWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPIUpdateSSOConnectionWithBodyWithResponse(ctx context.Context, id, contentType string, body io.Reader) (*sdk.SSOAPIUpdateSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPIUpdateSSOConnectionWithBodyWithResponse", ctx, id, contentType, body)
+ ret0, _ := ret[0].(*sdk.SSOAPIUpdateSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIUpdateSSOConnectionWithBodyWithResponse indicates an expected call of SSOAPIUpdateSSOConnectionWithBodyWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPIUpdateSSOConnectionWithBodyWithResponse(ctx, id, contentType, body interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIUpdateSSOConnectionWithBodyWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPIUpdateSSOConnectionWithBodyWithResponse), ctx, id, contentType, body)
+}
+
+// SSOAPIUpdateSSOConnectionWithResponse mocks base method.
+func (m *MockClientWithResponsesInterface) SSOAPIUpdateSSOConnectionWithResponse(ctx context.Context, id string, body sdk.SSOAPIUpdateSSOConnectionJSONRequestBody) (*sdk.SSOAPIUpdateSSOConnectionResponse, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SSOAPIUpdateSSOConnectionWithResponse", ctx, id, body)
+ ret0, _ := ret[0].(*sdk.SSOAPIUpdateSSOConnectionResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// SSOAPIUpdateSSOConnectionWithResponse indicates an expected call of SSOAPIUpdateSSOConnectionWithResponse.
+func (mr *MockClientWithResponsesInterfaceMockRecorder) SSOAPIUpdateSSOConnectionWithResponse(ctx, id, body interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SSOAPIUpdateSSOConnectionWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).SSOAPIUpdateSSOConnectionWithResponse), ctx, id, body)
+}
+
// ScheduledRebalancingAPICreateRebalancingJobWithBodyWithResponse mocks base method.
func (m *MockClientWithResponsesInterface) ScheduledRebalancingAPICreateRebalancingJobWithBodyWithResponse(ctx context.Context, clusterId, contentType string, body io.Reader) (*sdk.ScheduledRebalancingAPICreateRebalancingJobResponse, error) {
m.ctrl.T.Helper()
diff --git a/docs/resources/sso_connection.md b/docs/resources/sso_connection.md
new file mode 100644
index 00000000..6f6386eb
--- /dev/null
+++ b/docs/resources/sso_connection.md
@@ -0,0 +1,71 @@
+---
+page_title: "castai_sso_connection Resource - terraform-provider-castai"
+subcategory: ""
+description: |-
+ SSO Connection resource allows creating SSO trust relationship with CAST AI.
+---
+
+# castai_sso_connection (Resource)
+
+SSO Connection resource allows creating SSO trust relationship with CAST AI.
+
+## Example Usage
+
+```terraform
+resource "castai_sso_connection" "sso" {
+ name = "aad_connection"
+ email_domain = "aad_connection@test.com"
+ aad {
+ client_id = azuread_application.castai_sso.client_id
+ client_secret = azuread_application_password.castai_sso.value
+ ad_domain = azuread_application.castai_sso.publisher_domain
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `email_domain` (String) Email domain of the connection
+- `name` (String) Connection name
+
+### Optional
+
+- `aad` (Block List, Max: 1) Azure AD connector (see [below for nested schema](#nestedblock--aad))
+- `okta` (Block List, Max: 1) Okta connector (see [below for nested schema](#nestedblock--okta))
+- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+
+
+### Nested Schema for `aad`
+
+Required:
+
+- `ad_domain` (String) Azure AD domain
+- `client_id` (String) Azure AD client ID
+- `client_secret` (String, Sensitive) Azure AD client secret
+
+
+
+### Nested Schema for `okta`
+
+Required:
+
+- `client_id` (String) Okta client ID
+- `client_secret` (String, Sensitive) Okta client secret
+- `okta_domain` (String) Okta domain
+
+
+
+### Nested Schema for `timeouts`
+
+Optional:
+
+- `create` (String)
+- `delete` (String)
+- `update` (String)
diff --git a/examples/resources/sso_connection/resource.tf b/examples/resources/sso_connection/resource.tf
new file mode 100644
index 00000000..728fb310
--- /dev/null
+++ b/examples/resources/sso_connection/resource.tf
@@ -0,0 +1,9 @@
+resource "castai_sso_connection" "sso" {
+ name = "aad_connection"
+ email_domain = "aad_connection@test.com"
+ aad {
+ client_id = azuread_application.castai_sso.client_id
+ client_secret = azuread_application_password.castai_sso.value
+ ad_domain = azuread_application.castai_sso.publisher_domain
+ }
+}
diff --git a/examples/sso_connection/README.md b/examples/sso_connection/README.md
new file mode 100644
index 00000000..ed9ae416
--- /dev/null
+++ b/examples/sso_connection/README.md
@@ -0,0 +1,12 @@
+## CAST AI example for creating SSO connection
+
+Following example shows how setup Azure AD to create SSO trust relationship with CAST AI.
+
+Prerequisites:
+- CAST AI account
+- Obtained CAST AI [API Access key](https://docs.cast.ai/docs/authentication#obtaining-api-access-key) with Full Access
+
+1. Rename `tf.vars.example` to `tf.vars`
+2. Update `tf.vars` file.
+3. Run `terraform init`
+4. Run `terraform apply apply -var-file=tf.vars`
\ No newline at end of file
diff --git a/examples/sso_connection/azure.tf b/examples/sso_connection/azure.tf
new file mode 100644
index 00000000..44b45d22
--- /dev/null
+++ b/examples/sso_connection/azure.tf
@@ -0,0 +1,44 @@
+data "azuread_client_config" "current" {}
+
+resource "azuread_application" "castai_sso" {
+ display_name = "castai_sso"
+
+ web {
+ redirect_uris = ["https://login.cast.ai/login/callback"]
+ }
+
+ required_resource_access {
+ resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
+
+ resource_access {
+ id = azuread_service_principal.msgraph.app_role_ids["Directory.Read.All"]
+ type = "Role"
+ }
+
+ resource_access {
+ id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["User.Read"]
+ type = "Scope"
+ }
+ }
+}
+
+resource "azuread_application_password" "castai_sso" {
+ application_id = azuread_application.castai_sso.id
+}
+
+data "azuread_application_published_app_ids" "well_known" {}
+
+resource "azuread_service_principal" "msgraph" {
+ client_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
+ use_existing = true
+}
+
+resource "azuread_service_principal" "castai_sso" {
+ client_id = azuread_application.castai_sso.client_id
+}
+
+resource "azuread_app_role_assignment" "this" {
+ app_role_id = azuread_service_principal.msgraph.app_role_ids["Directory.Read.All"]
+ principal_object_id = azuread_service_principal.castai_sso.object_id
+ resource_object_id = azuread_service_principal.msgraph.object_id
+}
diff --git a/examples/sso_connection/main.tf b/examples/sso_connection/main.tf
new file mode 100644
index 00000000..4bd963ce
--- /dev/null
+++ b/examples/sso_connection/main.tf
@@ -0,0 +1,23 @@
+resource "castai_sso_connection" "sso" {
+ name = "azure_sso"
+ email_domain = azuread_application.castai_sso.publisher_domain
+ aad {
+ client_id = azuread_application.castai_sso.client_id
+ client_secret = azuread_application_password.castai_sso.value
+ ad_domain = azuread_application.castai_sso.publisher_domain
+ }
+ depends_on = [time_sleep.wait_10_seconds]
+}
+
+# Since creating castai_sso_connection immediately using azuread credentials fails with
+# 'The identity of the calling application could not be established' or
+# 'ClientSecretCredential authentication failed' for the sake of this example
+# we will use a simple sleep to ensure this example will work out of the box.
+resource "time_sleep" "wait_10_seconds" {
+ depends_on = [
+ azuread_app_role_assignment.this,
+ azuread_application_password.castai_sso
+ ]
+
+ create_duration = "10s"
+}
diff --git a/examples/sso_connection/providers.tf b/examples/sso_connection/providers.tf
new file mode 100644
index 00000000..168b217e
--- /dev/null
+++ b/examples/sso_connection/providers.tf
@@ -0,0 +1,8 @@
+provider "castai" {
+ api_url = var.castai_api_url
+ api_token = var.castai_api_token
+}
+
+provider "azurerm" {
+ features {}
+}
diff --git a/examples/sso_connection/tf.vars.example b/examples/sso_connection/tf.vars.example
new file mode 100644
index 00000000..a6a4ce09
--- /dev/null
+++ b/examples/sso_connection/tf.vars.example
@@ -0,0 +1,2 @@
+castai_api_url = "PLACEHOLDER"
+castai_api_token = "PLACEHOLDER"
diff --git a/examples/sso_connection/variables.tf b/examples/sso_connection/variables.tf
new file mode 100644
index 00000000..0ce1430c
--- /dev/null
+++ b/examples/sso_connection/variables.tf
@@ -0,0 +1,10 @@
+variable "castai_api_token" {
+ type = string
+ description = "CAST AI API token created in console.cast.ai API Access keys section."
+}
+
+variable "castai_api_url" {
+ type = string
+ description = "CAST AI api url."
+ default = "https://api.cast.ai"
+}
diff --git a/examples/sso_connection/versions.tf b/examples/sso_connection/versions.tf
new file mode 100644
index 00000000..bdd5cd22
--- /dev/null
+++ b/examples/sso_connection/versions.tf
@@ -0,0 +1,16 @@
+terraform {
+ required_providers {
+ castai = {
+ source = "castai/castai"
+ version = ">= 5.8.0"
+ }
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = ">= 3.79.0"
+ }
+ azuread = {
+ source = "hashicorp/azuread"
+ version = ">= 2.45.0"
+ }
+ }
+}
diff --git a/templates/resources/sso_connection.md.tmpl b/templates/resources/sso_connection.md.tmpl
new file mode 100644
index 00000000..f5199d33
--- /dev/null
+++ b/templates/resources/sso_connection.md.tmpl
@@ -0,0 +1,16 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: ""
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+## Example Usage
+
+{{ tffile "examples/resources/sso_connection/resource.tf" }}
+
+{{ .SchemaMarkdown | trimspace }}