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

Remove Hashing From Service Endpoints #856

Merged
merged 8 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ func TestAccServiceEndpointAws_Basic(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
resource.TestCheckResourceAttr(tfSvcEpNode, "access_key_id", "0000"),
resource.TestCheckResourceAttr(tfSvcEpNode, "secret_access_key", ""),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "secret_access_key_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "secret_access_key", "secretkey"),
),
},
},
Expand Down Expand Up @@ -61,11 +60,9 @@ func TestAccServiceEndpointAws_Complete(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
resource.TestCheckResourceAttr(tfSvcEpNode, "access_key_id", "0000"),
resource.TestCheckResourceAttr(tfSvcEpNode, "secret_access_key", ""),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "secret_access_key_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "secret_access_key", "secretkey"),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
resource.TestCheckResourceAttr(tfSvcEpNode, "session_token", ""),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "session_token_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "session_token", "foobar"),
resource.TestCheckResourceAttr(tfSvcEpNode, "role_to_assume", rta),
resource.TestCheckResourceAttr(tfSvcEpNode, "role_session_name", rsn),
resource.TestCheckResourceAttr(tfSvcEpNode, "external_id", externalId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ func TestAccServiceEndpointAzureRm_CreateAndUpdate(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "azurerm_subscription_id"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "azurerm_subscription_name"),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalid", serviceprincipalidFirst),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "credentials.0.serviceprincipalkey_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalkey", serviceprincipalkeyFirst),
),
}, {
Expand All @@ -55,7 +54,6 @@ func TestAccServiceEndpointAzureRm_CreateAndUpdate(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "azurerm_subscription_name"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalid", serviceprincipalidSecond),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "credentials.0.serviceprincipalkey_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalkey", serviceprincipalkeySecond),
),
},
Expand Down Expand Up @@ -86,7 +84,6 @@ func TestAccServiceEndpointAzureRm_MgmtGrpCreateAndUpdate(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "azurerm_management_group_id"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "azurerm_management_group_name"),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalid", serviceprincipalid),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "credentials.0.serviceprincipalkey_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "credentials.0.serviceprincipalkey", serviceprincipalkey),
),
},
Expand All @@ -101,7 +98,7 @@ func TestAccServiceEndpointAzureRm_AutomaticCreateAndUpdate(t *testing.T) {

tenantId := "9c59cbe5-2ca1-4516-b303-8968a070edd2"
subscriptionId := "3b0fee91-c36d-4d70-b1e9-fc4b9d608c3d"
subscriptionName := "Microsoft Azure DEMO"
subscriptionName := "Visual Studio Enterprise"

if os.Getenv("TEST_ARM_SUBSCRIPTION_ID") != "" {
subscriptionId = os.Getenv("TEST_ARM_SUBSCRIPTION_ID")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ func TestAccServiceEndpointDockerRegistry_CreateAndUpdate(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_username", "testuser"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_email", "[email protected]"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_password", ""),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "docker_password_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_password", "secret"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameFirst),
testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameFirst),
),
Expand All @@ -44,8 +43,7 @@ func TestAccServiceEndpointDockerRegistry_CreateAndUpdate(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "docker_username"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "docker_email"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_password", ""),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "docker_password_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "docker_password", "secret"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameSecond)),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestAccServiceEndpointGenericGit_complete(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "repository_url", "https://dev.azure.com/org/project/_git/repository"),
resource.TestCheckResourceAttr(tfSvcEpNode, "username", "username"),
resource.TestCheckResourceAttr(tfSvcEpNode, "password", ""),
resource.TestCheckResourceAttr(tfSvcEpNode, "password", "password"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
resource.TestCheckResourceAttr(tfSvcEpNode, "enable_pipelines_access", "true"),
Expand Down Expand Up @@ -96,7 +96,7 @@ func TestAccServiceEndpointGenericGit_update(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "repository_url", "https://dev.azure.com/org/project/_git/repository"),
resource.TestCheckResourceAttr(tfSvcEpNode, "username", "username"),
resource.TestCheckResourceAttr(tfSvcEpNode, "password", ""),
resource.TestCheckResourceAttr(tfSvcEpNode, "password", "password"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
resource.TestCheckResourceAttr(tfSvcEpNode, "enable_pipelines_access", "false"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func TestAccServiceEndpointSonarCloud_complete(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
resource.TestCheckResourceAttr(tfSvcEpNode, "token", "redacted"),
),
},
},
Expand Down Expand Up @@ -88,6 +89,7 @@ func TestAccServiceEndpointSonarCloud_update(t *testing.T) {
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
resource.TestCheckResourceAttr(tfSvcEpNode, "token", "redacted2"),
),
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestAccServiceEndpointSonarQube_complete(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointName),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "token_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "token", "redacted"),
resource.TestCheckResourceAttr(tfSvcEpNode, "url", "https://url.com/"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
Expand Down Expand Up @@ -88,7 +88,7 @@ func TestAccServiceEndpointSonarQube_update(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameSecond),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
resource.TestCheckResourceAttrSet(tfSvcEpNode, "token_hash"),
resource.TestCheckResourceAttr(tfSvcEpNode, "token", "redacted2"),
resource.TestCheckResourceAttr(tfSvcEpNode, "url", "https://url.com/2"),
resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
Expand Down
14 changes: 5 additions & 9 deletions azuredevops/internal/service/serviceendpoint/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,12 @@ func doBaseFlattening(d *schema.ResourceData, serviceEndpoint *serviceendpoint.S
// makeProtectedSchema create protected schema
func makeProtectedSchema(r *schema.Resource, keyName, envVarName, description string) {
r.Schema[keyName] = &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc(envVarName, nil),
Description: description,
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc(envVarName, nil),
Description: description,
Sensitive: true,
}

secretHashKey, secretHashSchema := tfhelper.GenerateSecreteMemoSchema(keyName)
r.Schema[secretHashKey] = secretHashSchema
}

// makeUnprotectedSchema create unprotected schema
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/tfhelper"
)

// ResourceServiceEndpointAws schema and implementation for aws service endpoint resource
Expand All @@ -18,25 +17,19 @@ func ResourceServiceEndpointAws() *schema.Resource {
Description: "The AWS access key ID for signing programmatic requests.",
}
r.Schema["secret_access_key"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_AWS_SERVICE_CONNECTION_SECRET_ACCESS_KEY", nil),
Description: "The AWS secret access key for signing programmatic requests.",
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_AWS_SERVICE_CONNECTION_SECRET_ACCESS_KEY", nil),
Description: "The AWS secret access key for signing programmatic requests.",
Sensitive: true,
}
saSecretHashKey, saSecretHashSchema := tfhelper.GenerateSecreteMemoSchema("secret_access_key")
r.Schema[saSecretHashKey] = saSecretHashSchema
r.Schema["session_token"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_AWS_SERVICE_CONNECTION_SESSION_TOKEN", nil),
Description: "The AWS session token for signing programmatic requests.",
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AZDO_AWS_SERVICE_CONNECTION_SESSION_TOKEN", nil),
Description: "The AWS session token for signing programmatic requests.",
Sensitive: true,
}
stSecretHashKey, stSecretHashSchema := tfhelper.GenerateSecreteMemoSchema("session_token")
r.Schema[stSecretHashKey] = stSecretHashSchema
r.Schema["role_to_assume"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -81,12 +74,7 @@ func expandServiceEndpointAws(d *schema.ResourceData) (*serviceendpoint.ServiceE
func flattenServiceEndpointAws(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *uuid.UUID) {
doBaseFlattening(d, serviceEndpoint, projectID)

tfhelper.HelpFlattenSecret(d, "secret_access_key")
tfhelper.HelpFlattenSecret(d, "session_token")

d.Set("access_key_id", (*serviceEndpoint.Authorization.Parameters)["username"])
d.Set("secret_access_key", (*serviceEndpoint.Authorization.Parameters)["password"])
d.Set("session_token", (*serviceEndpoint.Authorization.Parameters)["sessionToken"])
d.Set("role_to_assume", (*serviceEndpoint.Authorization.Parameters)["assumeRoleArn"])
d.Set("role_session_name", (*serviceEndpoint.Authorization.Parameters)["roleSessionName"])
d.Set("external_id", (*serviceEndpoint.Authorization.Parameters)["externalId"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ var awsTestServiceEndpoint = serviceendpoint.ServiceEndpoint{
Authorization: &serviceendpoint.EndpointAuthorization{
Parameters: &map[string]string{
"username": "AWS_TEST_username",
"password": "AWS_TEST_password",
"sessionToken": "AWS_TEST_sessionToken",
"password": "",
"sessionToken": "",
"assumeRoleArn": "AWS_TEST_assumeRoleArn",
"roleSessionName": "ARS_TEST_roleSessionName",
"externalId": "AWS_TEST_externalId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/tfhelper"
)

func ResourceServiceEndpointAzureDevOps() *schema.Resource {
Expand Down Expand Up @@ -49,6 +48,5 @@ func expandServiceEndpointAzureDevOps(d *schema.ResourceData) (*serviceendpoint.
func flattenServiceEndpointAzureDevOps(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *uuid.UUID) {
doBaseFlattening(d, serviceEndpoint, projectID)
d.Set("org_url", serviceEndpoint.Url)
tfhelper.HelpFlattenSecret(d, "password")
d.Set("release_api_url", (*serviceEndpoint.Data)["releaseUrl"])
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/service/serviceendpoint/migration"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/tfhelper"
)

// ResourceServiceEndpointAzureRM schema and implementation for AzureRM service endpoint resource
Expand All @@ -34,7 +33,6 @@ func ResourceServiceEndpointAzureRM() *schema.Resource {
makeUnprotectedOptionalSchema(r, "azurerm_management_group_id", "ARM_MGMT_GROUP_ID", "The Azure managementGroup Id which should be used.", []string{"azurerm_subscription_id", "resource_group"})
makeUnprotectedOptionalSchema(r, "azurerm_management_group_name", "ARM_MGMT_GROUP_NAME", "The Azure managementGroup name which should be used.", []string{"azurerm_subscription_id", "resource_group"})

secretHashKey, secretHashSchema := tfhelper.GenerateSecreteMemoSchema("serviceprincipalkey")
r.Schema["credentials"] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
Expand All @@ -48,13 +46,11 @@ func ResourceServiceEndpointAzureRM() *schema.Resource {
Description: "The service principal id which should be used.",
},
"serviceprincipalkey": {
Type: schema.TypeString,
Optional: true,
Description: "The service principal secret which should be used.",
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
Type: schema.TypeString,
Optional: true,
Description: "The service principal secret which should be used.",
Sensitive: true,
},
secretHashKey: secretHashSchema,
},
},
}
Expand Down Expand Up @@ -254,22 +250,6 @@ func expandServiceEndpointAzureRM(d *schema.ResourceData) (*serviceendpoint.Serv
return serviceEndpoint, projectID, nil
}

func flattenCredentials(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, hashKey string, hashValue string, serviceEndPointAuthenticationScheme AzureRmEndpointAuthenticationScheme) interface{} {
// secret value won't return by service and should not be overwritten
if serviceEndPointAuthenticationScheme == WorkloadIdentityFederation {
return []map[string]interface{}{{
"serviceprincipalid": (*serviceEndpoint.Authorization.Parameters)["serviceprincipalid"],
"serviceprincipalkey": d.Get("credentials.0.serviceprincipalkey").(string),
}}
} else {
return []map[string]interface{}{{
"serviceprincipalid": (*serviceEndpoint.Authorization.Parameters)["serviceprincipalid"],
"serviceprincipalkey": d.Get("credentials.0.serviceprincipalkey").(string),
hashKey: hashValue,
}}
}
}

// Convert AzDO data structure to internal Terraform data structure
func flattenServiceEndpointAzureRM(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *uuid.UUID) {
doBaseFlattening(d, serviceEndpoint, projectID)
Expand All @@ -282,9 +262,12 @@ func flattenServiceEndpointAzureRM(d *schema.ResourceData, serviceEndpoint *serv
}

if (*serviceEndpoint.Data)["creationMode"] == "Manual" {
newHash, hashKey := tfhelper.HelpFlattenSecretNested(d, "credentials", d.Get("credentials.0").(map[string]interface{}), "serviceprincipalkey")
credentials := flattenCredentials(d, serviceEndpoint, hashKey, newHash, serviceEndPointType)
d.Set("credentials", credentials)
if _, ok := d.GetOk("credentials"); !ok {
credentials := make(map[string]interface{})
credentials["serviceprincipalid"] = (*serviceEndpoint.Authorization.Parameters)["serviceprincipalid"]
credentials["serviceprincipalkey"] = d.Get("credentials.0.serviceprincipalkey").(string)
d.Set("credentials", []interface{}{credentials})
}
}

s := strings.SplitN(scope, "/", -1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func getManualAuthServiceEndpoint() serviceendpoint.ServiceEndpoint {
Parameters: &map[string]string{
"authenticationType": "spnKey",
"serviceprincipalid": "e31eaaac-47da-4156-b433-9b0538c94b7e", //fake value
"serviceprincipalkey": "d96d8515-20b2-4413-8879-27c5d040cbc2", //fake value
"serviceprincipalkey": "", //fake value
"tenantid": "aba07645-051c-44b4-b806-c34d33f3dcd1", //fake value
},
Scheme: converter.String("ServicePrincipal"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/model"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/tfhelper"
)

// ResourceServiceEndpointBitBucket schema and implementation for bitbucket service endpoint resource
Expand Down Expand Up @@ -34,5 +33,4 @@ func expandServiceEndpointBitBucket(d *schema.ResourceData) (*serviceendpoint.Se
func flattenServiceEndpointBitBucket(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *uuid.UUID) {
doBaseFlattening(d, serviceEndpoint, projectID)
d.Set("username", (*serviceEndpoint.Authorization.Parameters)["username"])
tfhelper.HelpFlattenSecret(d, "password")
}
Loading