Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resolved update not change the integration auth #78

Merged
merged 6 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/resources/integration_aws_parameter_store.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ resource "infisical_integration_aws_parameter_store" "parameter-store-integratio
environment = "<env-slug>" // example, dev

secret_path = "<infisical-secrets-path>" // example, /folder, or /
parameter_store_path = "/example/secrets"
parameter_store_path = "/example/secrets/"

aws_region = "<aws-region>" // example, us-east-2

Expand Down
4 changes: 2 additions & 2 deletions docs/resources/integration_aws_secrets_manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ resource "infisical_integration_aws_secrets_manager" "secrets-manager-integratio

secret_path = "<infisical-secrets-path>" // example, /folder, or /

secrets_manager_path = "/example/secrets" # Only required if mapping_behavior is one-to-one
mapping_behavior = "one-to-one" # Optional, default is many-to-one
secrets_manager_path = "/example/secrets/" # Only required if mapping_behavior is one-to-one
mapping_behavior = "one-to-one" # Optional, default is many-to-one

# AWS Authentication
access_key_id = "<aws-access-key-id>"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ resource "infisical_integration_aws_parameter_store" "parameter-store-integratio
environment = "<env-slug>" // example, dev

secret_path = "<infisical-secrets-path>" // example, /folder, or /
parameter_store_path = "/example/secrets"
parameter_store_path = "/example/secrets/"

aws_region = "<aws-region>" // example, us-east-2

Expand All @@ -40,4 +40,5 @@ resource "infisical_integration_aws_parameter_store" "parameter-store-integratio
},
]
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ resource "infisical_integration_aws_secrets_manager" "secrets-manager-integratio

secret_path = "<infisical-secrets-path>" // example, /folder, or /

secrets_manager_path = "/example/secrets" # Only required if mapping_behavior is one-to-one
mapping_behavior = "one-to-one" # Optional, default is many-to-one
secrets_manager_path = "/example/secrets/" # Only required if mapping_behavior is one-to-one
mapping_behavior = "one-to-one" # Optional, default is many-to-one

# AWS Authentication
access_key_id = "<aws-access-key-id>"
Expand All @@ -38,4 +38,5 @@ resource "infisical_integration_aws_secrets_manager" "secrets-manager-integratio
},
]
}
}
}

20 changes: 20 additions & 0 deletions internal/client/integrations_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ func (client Client) CreateIntegrationAuth(request CreateIntegrationAuthRequest)
return body, nil
}

func (client Client) UpdateIntegrationAuth(request UpdateIntegrationAuthRequest) (UpdateIntegrationAuthResponse, error) {
var body UpdateIntegrationAuthResponse
response, err := client.Config.HttpClient.
R().
SetResult(&body).
SetHeader("User-Agent", USER_AGENT).
SetBody(request).
Patch("api/v1/integration-auth/" + request.IntegrationAuthId)

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

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

return body, nil
}

// Deleting integration auth triggers a cascade effect, that will also delete the associated integration.
func (client Client) DeleteIntegrationAuth(request DeleteIntegrationAuthRequest) (DeleteIntegrationAuthResponse, error) {
var body DeleteIntegrationAuthResponse
Expand Down
18 changes: 18 additions & 0 deletions internal/client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -1552,12 +1552,28 @@ type CreateIntegrationAuthRequest struct {
Integration IntegrationAuthType `json:"integration"`
}

type UpdateIntegrationAuthRequest struct {
AccessId string `json:"accessId,omitempty"`
AccessToken string `json:"accessToken,omitempty"`
AWSAssumeIamRoleArn string `json:"awsAssumeIamRoleArn,omitempty"`
RefreshToken string `json:"refreshToken,omitempty"`
URL string `json:"url,omitempty"`
Integration IntegrationAuthType `json:"integration"`
IntegrationAuthId string `json:"integrationAuthId"`
}

type CreateIntegrationAuthResponse struct {
IntegrationAuth struct {
ID string `json:"id"`
} `json:"integrationAuth"`
}

type UpdateIntegrationAuthResponse struct {
IntegrationAuth struct {
ID string `json:"id"`
} `json:"integrationAuth"`
}

type DeleteIntegrationAuthRequest struct {
ID string `json:"id"`
}
Expand Down Expand Up @@ -1661,6 +1677,8 @@ type UpdateIntegrationRequest struct {
Environment string `json:"environment,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
IsActive bool `json:"isActive"`
Region string `json:"region,omitempty"`
Path string `json:"path,omitempty"`
}

type UpdateIntegrationResponse struct {
Expand Down
55 changes: 35 additions & 20 deletions internal/provider/resource/integration_aws_parameter_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,29 +125,25 @@ func (r *IntegrationAWSParameterStoreResource) Schema(_ context.Context, _ resou
},

"aws_region": schema.StringAttribute{
Required: true,
Description: "The AWS region to sync secrets to. (us-east-1, us-east-2, etc)",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Required: true,
Description: "The AWS region to sync secrets to. (us-east-1, us-east-2, etc)",
},

"access_key_id": schema.StringAttribute{
Sensitive: true,
Optional: true,
Description: "The AWS access key ID. Used to authenticate with AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Sensitive: true,
Optional: true,
Description: "The AWS access key ID. Used to authenticate with AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"secret_access_key": schema.StringAttribute{
Sensitive: true,
Optional: true,
Description: "The AWS secret access key. Used to authenticate with AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Sensitive: true,
Optional: true,
Description: "The AWS secret access key. Used to authenticate with AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"assume_role_arn": schema.StringAttribute{
Optional: true,
Description: "The ARN of the role to assume when syncing secrets to AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Optional: true,
Description: "The ARN of the role to assume when syncing secrets to AWS Parameter Store. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"project_id": schema.StringAttribute{
Expand All @@ -157,9 +153,8 @@ func (r *IntegrationAWSParameterStoreResource) Schema(_ context.Context, _ resou
},

"parameter_store_path": schema.StringAttribute{
Required: true,
Description: "The path in AWS Parameter Store to sync secrets to.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Required: true,
Description: "The path in AWS Parameter Store to sync secrets to.",
},

"environment": schema.StringAttribute{
Expand Down Expand Up @@ -214,7 +209,6 @@ func (r *IntegrationAWSParameterStoreResource) Create(ctx context.Context, req r
}

authMethod, err := pkg.ValidateAwsInputCredentials(plan.AccessKeyID, plan.SecretAccessKey, plan.AssumeRoleArn)

if err != nil {
resp.Diagnostics.AddError(
"Error validating AWS credentials",
Expand Down Expand Up @@ -392,8 +386,7 @@ func (r *IntegrationAWSParameterStoreResource) Update(ctx context.Context, req r
return
}

_, err := pkg.ValidateAwsInputCredentials(plan.AccessKeyID, plan.SecretAccessKey, plan.AssumeRoleArn)

authMethod, err := pkg.ValidateAwsInputCredentials(plan.AccessKeyID, plan.SecretAccessKey, plan.AssumeRoleArn)
if err != nil {
resp.Diagnostics.AddError(
"Error validating AWS credentials",
Expand All @@ -412,6 +405,26 @@ func (r *IntegrationAWSParameterStoreResource) Update(ctx context.Context, req r
}
}

updateIntegrationAuthRequest := infisical.UpdateIntegrationAuthRequest{
Integration: infisical.IntegrationAuthTypeAwsSecretsManager,
IntegrationAuthId: plan.IntegrationAuthID.String(),
akhilmhdh marked this conversation as resolved.
Show resolved Hide resolved
}
if authMethod == pkg.AwsAuthMethodAccessKey {
updateIntegrationAuthRequest.AccessId = plan.AccessKeyID.ValueString()
updateIntegrationAuthRequest.AccessToken = plan.SecretAccessKey.ValueString()
} else if authMethod == pkg.AwsAuthMethodAssumeRole {
updateIntegrationAuthRequest.AWSAssumeIamRoleArn = plan.AssumeRoleArn.ValueString()
}

_, err = r.client.UpdateIntegrationAuth(updateIntegrationAuthRequest)
if err != nil {
resp.Diagnostics.AddError(
"Error updating integration auth",
err.Error(),
)
return
}
akhilmhdh marked this conversation as resolved.
Show resolved Hide resolved

// Convert metadata to map[string]interface{} if needed
metadataMap := map[string]interface{}{}

Expand All @@ -428,6 +441,8 @@ func (r *IntegrationAWSParameterStoreResource) Update(ctx context.Context, req r
Metadata: metadataMap,
Environment: plan.Environment.ValueString(),
SecretPath: plan.SecretPath.ValueString(),
Region: plan.AWSRegion.ValueString(),
Path: plan.AWSPath.String(),
akhilmhdh marked this conversation as resolved.
Show resolved Hide resolved
})

if err != nil {
Expand Down
93 changes: 65 additions & 28 deletions internal/provider/resource/integration_aws_secrets_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,29 +130,25 @@ func (r *IntegrationAWSSecretsManagerResource) Schema(_ context.Context, _ resou
},

"aws_region": schema.StringAttribute{
Required: true,
Description: "The AWS region to sync secrets to. (us-east-1, us-east-2, etc)",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Required: true,
Description: "The AWS region to sync secrets to. (us-east-1, us-east-2, etc)",
},

"access_key_id": schema.StringAttribute{
Sensitive: true,
Optional: true,
Description: "The AWS access key ID. Used to authenticate with AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Sensitive: true,
Optional: true,
Description: "The AWS access key ID. Used to authenticate with AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"secret_access_key": schema.StringAttribute{
Sensitive: true,
Optional: true,
Description: "The AWS secret access key. Used to authenticate with AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Sensitive: true,
Optional: true,
Description: "The AWS secret access key. Used to authenticate with AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"assume_role_arn": schema.StringAttribute{
Optional: true,
Description: "The ARN of the role to assume when syncing secrets to AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Optional: true,
Description: "The ARN of the role to assume when syncing secrets to AWS Secrets Manager. You must either set secret_access_key and access_key_id, or set assume_role_arn to assume a role.",
},

"project_id": schema.StringAttribute{
Expand All @@ -174,9 +170,8 @@ func (r *IntegrationAWSSecretsManagerResource) Schema(_ context.Context, _ resou
},

"secrets_manager_path": schema.StringAttribute{
Optional: true,
Description: "The path in AWS Secrets Manager to sync secrets to. This is required if mapping_behavior is 'many-to-one'.",
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Optional: true,
Description: "The path in AWS Secrets Manager to sync secrets to. This is required if mapping_behavior is 'many-to-one'.",
},

"secret_path": schema.StringAttribute{
Expand Down Expand Up @@ -434,8 +429,38 @@ func (r *IntegrationAWSSecretsManagerResource) Update(ctx context.Context, req r
return
}

_, err := pkg.ValidateAwsInputCredentials(plan.AccessKeyID, plan.SecretAccessKey, plan.AssumeRoleArn)
var planOptions AwsSecretsManagerOptions

if !plan.Options.IsNull() {
diags := plan.Options.As(ctx, &planOptions, basetypes.ObjectAsOptions{})
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

if plan.MappingBehavior.ValueString() == MAPPING_BEHAVIOR_MANY_TO_ONE && (plan.AWSPath.IsNull() || plan.AWSPath.ValueString() == "") {
resp.Diagnostics.AddError(
"Invalid plan",
"secrets_manager_path is required when mapping_behavior is 'many-to-one'",
)
return
}

if plan.MappingBehavior.ValueString() == MAPPING_BEHAVIOR_ONE_TO_ONE && (!plan.AWSPath.IsNull() && plan.AWSPath.ValueString() != "") {
resp.Diagnostics.AddError(
"Invalid plan",
"secrets_manager_path should not be used when mapping_behavior is 'one-to-one'",
)
return
}

updateIntegrationAuthRequest := infisical.UpdateIntegrationAuthRequest{
Integration: infisical.IntegrationAuthTypeAwsSecretsManager,
IntegrationAuthId: plan.IntegrationAuthID.String(),
akhilmhdh marked this conversation as resolved.
Show resolved Hide resolved
}

authMethod, err := pkg.ValidateAwsInputCredentials(plan.AccessKeyID, plan.SecretAccessKey, plan.AssumeRoleArn)
if err != nil {
resp.Diagnostics.AddError(
"Error validating AWS credentials",
Expand All @@ -444,14 +469,20 @@ func (r *IntegrationAWSSecretsManagerResource) Update(ctx context.Context, req r
return
}

var planOptions AwsSecretsManagerOptions
if authMethod == pkg.AwsAuthMethodAccessKey {
updateIntegrationAuthRequest.AccessId = plan.AccessKeyID.ValueString()
updateIntegrationAuthRequest.AccessToken = plan.SecretAccessKey.ValueString()
} else if authMethod == pkg.AwsAuthMethodAssumeRole {
updateIntegrationAuthRequest.AWSAssumeIamRoleArn = plan.AssumeRoleArn.ValueString()
}

sheensantoscapadngan marked this conversation as resolved.
Show resolved Hide resolved
if !plan.Options.IsNull() {
diags := plan.Options.As(ctx, &planOptions, basetypes.ObjectAsOptions{})
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
_, err = r.client.UpdateIntegrationAuth(updateIntegrationAuthRequest)
if err != nil {
resp.Diagnostics.AddError(
"Error updating integration auth",
err.Error(),
)
return
}

// Convert metadata to map[string]interface{} if needed
Expand All @@ -468,13 +499,19 @@ func (r *IntegrationAWSSecretsManagerResource) Update(ctx context.Context, req r
metadataMap["secretAWSTag"] = []infisical.AwsTag{}
}

// Update the integration
updatedIntegration, err := r.client.UpdateIntegration(infisical.UpdateIntegrationRequest{
updateIntegrationRequest := infisical.UpdateIntegrationRequest{
ID: state.IntegrationID.ValueString(),
Metadata: metadataMap,
Environment: plan.Environment.ValueString(),
SecretPath: plan.SecretPath.ValueString(),
})
Region: plan.AWSRegion.ValueString(),
}
if plan.MappingBehavior.ValueString() == MAPPING_BEHAVIOR_MANY_TO_ONE {
updateIntegrationRequest.App = plan.AWSPath.ValueString()
}

// Update the integration
updatedIntegration, err := r.client.UpdateIntegration(updateIntegrationRequest)

if err != nil {
resp.Diagnostics.AddError(
Expand Down
Loading
Loading