Skip to content

Commit

Permalink
Merge pull request #49 from swapnilkuwar/secret-import-resource-impl
Browse files Browse the repository at this point in the history
Infisical import secret resource added.
  • Loading branch information
DanielHougaard authored Oct 2, 2024
2 parents e0fbb64 + fa8ac86 commit 75a3647
Show file tree
Hide file tree
Showing 8 changed files with 559 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ website/vendor

# Keep windows files with windows line endings
*.winfile eol=crlf
terraform-provider-infisical
29 changes: 29 additions & 0 deletions docs/resources/secret_import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "infisical_secret_import Resource - terraform-provider-infisical"
subcategory: ""
description: |-
Create secret import & save to Infisical.
---

# infisical_secret_import (Resource)

Create secret import & save to Infisical.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `environment_slug` (String) The environment slug of the secret import to modify/create
- `folder_path` (String) The path where the secret should be imported
- `import_environment_slug` (String) The environment slug of the secret import to modify/create
- `import_folder_path` (String) The path where the secret should be imported from
- `is_replication` (Boolean) The is_replication of the secret import to modify/create
- `project_id` (String) The Infisical project ID

### Read-Only

- `id` (String) The ID of the secret import
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
terraform {
required_providers {
infisical = {
# version = <latest version>
source = "infisical/infisical"
}
}
}

provider "infisical" {
host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com
client_id = "<>"
client_secret = "<>"
}

resource "infisical_secret_import" "custom-import" {
environment_slug = "<ENV_SLUG>"
import_environment_slug = "<ENV_SLUG>"
is_replication = false
project_id = "<PROJECT-ID>"
folder_path = "<FOLDER_PATH>"
import_folder_path = "<IMPORT_FOLDER_PATH>"
}
18 changes: 18 additions & 0 deletions internal/client/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ type DecodedSymmetricEncryptionDetails = struct {
Key []byte
}

// Define a generic not found error type.
type NotFoundError struct {
Resource string
ID string
}

func GetBase64DecodedSymmetricEncryptionDetails(key string, cipher string, IV string, tag string) (DecodedSymmetricEncryptionDetails, error) {
cipherx, err := base64.StdEncoding.DecodeString(cipher)
if err != nil {
Expand Down Expand Up @@ -51,3 +57,15 @@ func GetSymmetricKeyFromServiceToken(serviceToken string) (privateKey string, er

return serviceTokenParts[3], nil
}

func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s with ID %s not found", e.Resource, e.ID)
}

// A helper function to create a new NotFoundError.
func NewNotFoundError(resource, id string) error {
return &NotFoundError{
Resource: resource,
ID: id,
}
}
68 changes: 68 additions & 0 deletions internal/client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ type SecretFolder struct {
EnvID string `json:"envId"`
}

type SecretImport struct {
ID string `json:"id"`
SecretPath string `json:"secretPath"`
ImportPath string `json:"importPath"`
}

type CreateProjectResponse struct {
Project Project `json:"project"`
}
Expand Down Expand Up @@ -1554,3 +1560,65 @@ type DeleteAccessApprovalPolicyRequest struct {
type DeleteAccessApprovalPolicyResponse struct {
AccessApprovalPolicy AccessApprovalPolicy `json:"approval"`
}
type CreateSecretImportRequest struct {
ProjectID string `json:"workspaceId"`
Environment string `json:"environment"`
SecretPath string `json:"path"`
IsReplication bool `json:"isReplication"`
ImportFrom struct {
Environment string `json:"environment"`
SecretPath string `json:"path"`
} `json:"import"`
}

type CreateSecretImportResponse struct {
SecretImport SecretImport `json:"secretImport"`
}

type UpdateSecretImportRequest struct {
ID string `json:"id"`
ProjectID string `json:"workspaceId"`
Environment string `json:"environment"`
SecretPath string `json:"path"`
IsReplication bool `json:"isReplication"`
ImportFrom struct {
Environment string `json:"environment"`
SecretPath string `json:"path"`
} `json:"import"`
}

type UpdateSecretImportResponse struct {
SecretImport SecretImport `json:"secretImport"`
}

type DeleteSecretImportRequest struct {
ID string `json:"id"`
Environment string `json:"environment"`
ProjectID string `json:"workspaceId"`
SecretPath string `json:"path"`
}

type DeleteSecretImportResponse struct {
SecretImport SecretImport `json:"secretImport"`
}

type GetSecretImportByIDRequest struct {
ID string `json:"id"`
Environment string `json:"environment"`
ProjectID string `json:"workspaceId"`
SecretPath string `json:"path"`
}

type GetSecretImportByIDResponse struct {
SecretImport SecretImport `json:"secretImport"`
}

type ListSecretImportRequest struct {
Environment string `json:"environment"`
ProjectID string `json:"workspaceId"`
SecretPath string `json:"path"`
}

type ListSecretImportResponse struct {
SecretImports []SecretImport `json:"secretImports"`
}
134 changes: 134 additions & 0 deletions internal/client/secret_import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package infisicalclient

import (
"fmt"
"net/http"
)

// Workaround to getSecretImportById API call.
func findSecretImportByID(secretImports []SecretImport, id string) (GetSecretImportByIDResponse, error) {
for _, secretImport := range secretImports {
if secretImport.ID == id {
return GetSecretImportByIDResponse{SecretImport: secretImport}, nil
}
}

return GetSecretImportByIDResponse{}, NewNotFoundError("SecretImport", id)
}

func (client Client) GetSecretImportByID(request GetSecretImportByIDRequest) (GetSecretImportByIDResponse, error) {
var body ListSecretImportResponse

httpRequest := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetQueryParam("workspaceId", request.ProjectID).
SetQueryParam("environment", request.Environment).
SetQueryParam("path", request.SecretPath)

response, err := httpRequest.Get("api/v1/secret-imports")

if err != nil {
return GetSecretImportByIDResponse{}, fmt.Errorf("GetSecretImportByID: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return GetSecretImportByIDResponse{}, fmt.Errorf("GetSecretImportByID: Unsuccessful response. [response=%v]", string(response.Body()))
}

return findSecretImportByID(body.SecretImports, request.ID)

}

func (client Client) GetSecretImportList(request ListSecretImportRequest) (ListSecretImportResponse, error) {
var body ListSecretImportResponse

httpRequest := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetQueryParam("workspaceId", request.ProjectID).
SetQueryParam("environment", request.Environment).
SetQueryParam("path", request.SecretPath)

response, err := httpRequest.Get("api/v1/secret-imports")

if err != nil {
return ListSecretImportResponse{}, fmt.Errorf("ListSecretImport: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return ListSecretImportResponse{}, fmt.Errorf("ListSecretImport: Unsuccessful response. [response=%v]", string(response.Body()))
}

return body, nil
}

func (client Client) CreateSecretImport(request CreateSecretImportRequest) (CreateSecretImportResponse, error) {
var body CreateSecretImportResponse
response, err := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetBody(request).
Post("api/v1/secret-imports")

if err != nil {
return CreateSecretImportResponse{}, fmt.Errorf("CallCreateSecretImport: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
return CreateSecretImportResponse{}, fmt.Errorf("CallCreateSecretImport: Unsuccessful response. [response=%s]", string(response.Body()))
}

return body, nil
}

func (client Client) UpdateSecretImport(request UpdateSecretImportRequest) (UpdateSecretImportResponse, error) {
var body UpdateSecretImportResponse
response, err := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetBody(request).
Patch("api/v1/secret-imports/" + request.ID)

if err != nil {
return UpdateSecretImportResponse{}, fmt.Errorf("CallUpdateSecretImport: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
if response.StatusCode() == http.StatusNotFound {
return UpdateSecretImportResponse{}, NewNotFoundError("SecretImport", request.SecretPath)
}

return UpdateSecretImportResponse{}, fmt.Errorf("CallUpdateSecretImport: Unsuccessful response. [response=%s]", string(response.Body()))
}

return body, nil
}

func (client Client) DeleteSecretImport(request DeleteSecretImportRequest) (DeleteSecretImportResponse, error) {
var body DeleteSecretImportResponse
response, err := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetBody(request).
Delete("api/v1/secret-imports/" + request.ID)

if err != nil {
return DeleteSecretImportResponse{}, fmt.Errorf("CallDeleteSecretImport: Unable to complete api request [err=%s]", err)
}

if response.IsError() {
if response.StatusCode() == http.StatusNotFound {
return DeleteSecretImportResponse{}, NewNotFoundError("SecretImport", request.SecretPath)
}

return DeleteSecretImportResponse{}, fmt.Errorf("CallDeleteSecretImport: Unsuccessful response. [response=%s]", string(response.Body()))
}

return body, nil
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,6 @@ func (p *infisicalProvider) Resources(_ context.Context) []func() resource.Resou
infisicalResource.NewIdentityOidcAuthResource,
infisicalResource.NewSecretApprovalPolicyResource,
infisicalResource.NewAccessApprovalPolicyResource,
infisicalResource.NewProjectSecretImportResource,
}
}
Loading

0 comments on commit 75a3647

Please sign in to comment.