diff --git a/cyral/internal/sidecar/credentials/constants.go b/cyral/internal/sidecar/credentials/constants.go new file mode 100644 index 00000000..c30abaaf --- /dev/null +++ b/cyral/internal/sidecar/credentials/constants.go @@ -0,0 +1,5 @@ +package credentials + +const ( + resourceName = "cyral_sidecar_credentials" +) diff --git a/cyral/internal/sidecar/credentials/model.go b/cyral/internal/sidecar/credentials/model.go new file mode 100644 index 00000000..ac589424 --- /dev/null +++ b/cyral/internal/sidecar/credentials/model.go @@ -0,0 +1,38 @@ +package credentials + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type CreateSidecarCredentialsRequest struct { + SidecarID string `json:"sidecarId"` +} + +func (r *CreateSidecarCredentialsRequest) ReadFromSchema(d *schema.ResourceData) error { + r.SidecarID = d.Get("sidecar_id").(string) + return nil +} + +type SidecarCredentialsData struct { + SidecarID string `json:"sidecarId"` + ClientID string `json:"clientId"` + ClientSecret string `json:"clientSecret"` +} + +func (r *SidecarCredentialsData) WriteToSchema(d *schema.ResourceData) error { + if err := d.Set("client_id", r.ClientID); err != nil { + return fmt.Errorf("error setting 'client_id' field: %w", err) + } + if r.ClientSecret != "" { + if err := d.Set("client_secret", r.ClientSecret); err != nil { + return fmt.Errorf("error setting 'client_secret' field: %w", err) + } + } + if err := d.Set("sidecar_id", r.SidecarID); err != nil { + return fmt.Errorf("error setting 'sidecar_id' field: %w", err) + } + d.SetId(r.ClientID) + return nil +} diff --git a/cyral/internal/sidecar/credentials/resource.go b/cyral/internal/sidecar/credentials/resource.go new file mode 100644 index 00000000..615b2f2f --- /dev/null +++ b/cyral/internal/sidecar/credentials/resource.go @@ -0,0 +1,58 @@ +package credentials + +import ( + "fmt" + + "github.com/cyralinc/terraform-provider-cyral/cyral/client" + "github.com/cyralinc/terraform-provider-cyral/cyral/core" + "github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var resourceContextHandler = core.DefaultContextHandler{ + ResourceName: resourceName, + ResourceType: resourcetype.Resource, + SchemaReaderFactory: func() core.SchemaReader { return &CreateSidecarCredentialsRequest{} }, + SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &SidecarCredentialsData{} }, + SchemaWriterFactoryPostMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &SidecarCredentialsData{} }, + BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string { + return fmt.Sprintf("https://%s/v1/users/sidecarAccounts", c.ControlPlane) + }, +} + +func resourceSchema() *schema.Resource { + return &schema.Resource{ + Description: "Create new [credentials for Cyral sidecar](https://cyral.com/docs/sidecars/sidecar-manage/#rotate-the-client-secret-for-a-sidecar).", + CreateContext: resourceContextHandler.CreateContext(), + ReadContext: resourceContextHandler.ReadContext(), + DeleteContext: resourceContextHandler.DeleteContext(), + + Schema: map[string]*schema.Schema{ + "id": { + Description: "Same as `client_id`.", + Type: schema.TypeString, + Computed: true, + }, + "sidecar_id": { + Description: "ID of the sidecar to create new credentials.", + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "client_id": { + Description: "Sidecar client ID.", + Type: schema.TypeString, + Computed: true, + }, + "client_secret": { + Description: "Sidecar client secret.", + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + }, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + } +} diff --git a/cyral/internal/sidecar/credentials/resource_cyral_sidecar_credentials.go b/cyral/internal/sidecar/credentials/resource_cyral_sidecar_credentials.go deleted file mode 100644 index 2fe820cd..00000000 --- a/cyral/internal/sidecar/credentials/resource_cyral_sidecar_credentials.go +++ /dev/null @@ -1,128 +0,0 @@ -package credentials - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - - "github.com/cyralinc/terraform-provider-cyral/cyral/client" - "github.com/cyralinc/terraform-provider-cyral/cyral/utils" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -type CreateSidecarCredentialsRequest struct { - SidecarID string `json:"sidecarId"` -} - -type SidecarCredentialsData struct { - SidecarID string `json:"sidecarId"` - ClientID string `json:"clientId"` - ClientSecret string `json:"clientSecret"` -} - -func ResourceSidecarCredentials() *schema.Resource { - return &schema.Resource{ - Description: "Create new [credentials for Cyral sidecar](https://cyral.com/docs/sidecars/sidecar-manage/#rotate-the-client-secret-for-a-sidecar).", - CreateContext: resourceSidecarCredentialsCreate, - ReadContext: resourceSidecarCredentialsRead, - DeleteContext: resourceSidecarCredentialsDelete, - - Schema: map[string]*schema.Schema{ - "id": { - Description: "Same as `client_id`.", - Type: schema.TypeString, - Computed: true, - }, - "sidecar_id": { - Description: "ID of the sidecar to create new credentials.", - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "client_id": { - Description: "Sidecar client ID.", - Type: schema.TypeString, - Computed: true, - }, - "client_secret": { - Description: "Sidecar client secret.", - Type: schema.TypeString, - Computed: true, - Sensitive: true, - }, - }, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - } -} - -func resourceSidecarCredentialsCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourceSidecarCredentialsCreate") - c := m.(*client.Client) - - payload := CreateSidecarCredentialsRequest{d.Get("sidecar_id").(string)} - - url := fmt.Sprintf("https://%s/v1/users/sidecarAccounts", c.ControlPlane) - - body, err := c.DoRequest(ctx, url, http.MethodPost, payload) - if err != nil { - return utils.CreateError("Unable to create sidecar credentials", fmt.Sprintf("%v", err)) - } - - response := SidecarCredentialsData{} - if err := json.Unmarshal(body, &response); err != nil { - return utils.CreateError("Unable to unmarshall JSON", fmt.Sprintf("%v", err)) - } - tflog.Debug(ctx, fmt.Sprintf("Response body (unmarshalled): %#v", response)) - - d.SetId(response.ClientID) - d.Set("client_id", response.ClientID) - d.Set("client_secret", response.ClientSecret) - - return resourceSidecarCredentialsRead(ctx, d, m) -} - -func resourceSidecarCredentialsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourceSidecarCredentialsRead") - c := m.(*client.Client) - - url := fmt.Sprintf("https://%s/v1/users/sidecarAccounts/%s", c.ControlPlane, d.Id()) - - body, err := c.DoRequest(ctx, url, http.MethodGet, nil) - if err != nil { - return utils.CreateError(fmt.Sprintf("Unable to read sidecar credentials. ClientID: %s", - d.Id()), fmt.Sprintf("%v", err)) - } - - response := SidecarCredentialsData{} - if err := json.Unmarshal(body, &response); err != nil { - return utils.CreateError("Unable to unmarshall JSON", fmt.Sprintf("%v", err)) - } - tflog.Debug(ctx, fmt.Sprintf("Response body (unmarshalled): %#v", response)) - - d.Set("sidecar_id", response.SidecarID) - d.Set("client_id", response.ClientID) - - tflog.Debug(ctx, "End resourceSidecarCredentialsRead") - - return diag.Diagnostics{} -} - -func resourceSidecarCredentialsDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourceSidecarCredentialsDelete") - c := m.(*client.Client) - - url := fmt.Sprintf("https://%s/v1/users/sidecarAccounts/%s", c.ControlPlane, d.Id()) - - if _, err := c.DoRequest(ctx, url, http.MethodDelete, nil); err != nil { - return utils.CreateError("Unable to delete sidecar credentials", fmt.Sprintf("%v", err)) - } - - tflog.Debug(ctx, "End resourceSidecarCredentialsDelete") - - return diag.Diagnostics{} -} diff --git a/cyral/internal/sidecar/credentials/resource_cyral_sidecar_credentials_test.go b/cyral/internal/sidecar/credentials/resource_test.go similarity index 100% rename from cyral/internal/sidecar/credentials/resource_cyral_sidecar_credentials_test.go rename to cyral/internal/sidecar/credentials/resource_test.go diff --git a/cyral/internal/sidecar/credentials/schema_loader.go b/cyral/internal/sidecar/credentials/schema_loader.go new file mode 100644 index 00000000..17a4fe9e --- /dev/null +++ b/cyral/internal/sidecar/credentials/schema_loader.go @@ -0,0 +1,26 @@ +package credentials + +import ( + "github.com/cyralinc/terraform-provider-cyral/cyral/core" +) + +type packageSchema struct { +} + +func (p *packageSchema) Name() string { + return "credentials" +} + +func (p *packageSchema) Schemas() []*core.SchemaDescriptor { + return []*core.SchemaDescriptor{ + { + Name: resourceName, + Type: core.ResourceSchemaType, + Schema: resourceSchema, + }, + } +} + +func PackageSchema() core.PackageSchema { + return &packageSchema{} +} diff --git a/cyral/provider/provider.go b/cyral/provider/provider.go index 5bca46ad..6d79dfc7 100644 --- a/cyral/provider/provider.go +++ b/cyral/provider/provider.go @@ -28,7 +28,6 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/internal/samlconfiguration" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/serviceaccount" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar" - "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar/credentials" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar/health" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar/instance" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar/listener" @@ -169,7 +168,6 @@ func getResourceMap(ps []core.PackageSchema) map[string]*schema.Resource { schemaMap["cyral_role"] = role.ResourceRole() schemaMap["cyral_role_sso_groups"] = role.ResourceRoleSSOGroups() schemaMap["cyral_service_account"] = serviceaccount.ResourceServiceAccount() - schemaMap["cyral_sidecar_credentials"] = credentials.ResourceSidecarCredentials() schemaMap["cyral_sidecar_listener"] = listener.ResourceSidecarListener() tflog.Debug(ctx, "End getResourceMap") diff --git a/cyral/provider/schema_loader.go b/cyral/provider/schema_loader.go index be2a9b5f..3af6c113 100644 --- a/cyral/provider/schema_loader.go +++ b/cyral/provider/schema_loader.go @@ -14,6 +14,7 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository/useraccount" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/samlcertificate" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar" + "github.com/cyralinc/terraform-provider-cyral/cyral/internal/sidecar/credentials" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/tokensettings" ) @@ -22,6 +23,7 @@ func packagesSchemas() []core.PackageSchema { accessgateway.PackageSchema(), accessrules.PackageSchema(), binding.PackageSchema(), + credentials.PackageSchema(), datalabel.PackageSchema(), datamap.PackageSchema(), hcvault.PackageSchema(),