jdamata / terraform-provider-sonarqube

Terraform provider for managing Sonarqube configuration
GNU General Public License v3.0
62 stars 54 forks source link

Cannot set secured settings #91

Open jorsmatthys opened 2 years ago

jorsmatthys commented 2 years ago

Hello,

I have the impression that the sonarqube_setting resource of the provider cannot handle secured settings at this point in time. We have a terraform project where we use the azuread provider to create an azuread app + service principal for terraform and then we want to configure the resulting values in sonarqube to enable azuread authentication. We fail to set the required application secret and application id.

Affected Resource(s)

Please list the resources as a list, for example:

Terraform Configuration Files

resource "sonarqube_setting" "aad-client-id" {
  key   = "sonar.auth.aad.clientId.secured"
  value = azuread_application.openid_aad_app.application_id
}

resource "sonarqube_setting" "aad-client-secret" {
  key   = "sonar.auth.aad.clientSecret.secured"
  value = azuread_service_principal_password.openid_aad_app_sp_secret.value
}

Expected Behavior

The setting should have been overwritten with the new/latest value.

Actual Behavior

Nothing, the terraform execution failed with:

│ Error: resourceSonarqubeSettingsRead: Failed to find setting: sonar.auth.aad.clientId.secured │ │ with sonarqube_setting.aad-client-id, │ on sonarqube-settings.tf line 6, in resource "sonarqube_setting" "aad-client-id": │ 6: resource "sonarqube_setting" "aad-client-id" { │ ╵ ╷ │ Error: resourceSonarqubeSettingsRead: Failed to find setting: sonar.auth.aad.clientSecret.secured │ │ with sonarqube_setting.aad-client-secret, │ on sonarqube-settings.tf line 11, in resource "sonarqube_setting" "aad-client-secret": │ 11: resource "sonarqube_setting" "aad-client-secret" { │

References / additional info:

I verified locally with curl and if you try to get the setting value with the key of a secured setting, you get a response from which you can deduct that the setting exists but is secured.

{
"settings":[],
"setSecuredSettings":["sonar.auth.aad.clientId.secured"]
}

Could the provider be adjusted so that, if the setting is secured, the setting can be written without checking the current value?

jdamata commented 1 year ago

What curl were you able to run to retrieve this setting?

tbutler-qontigo commented 1 year ago

@jdamata I can't find the setting that @jorsmatthys used but you can test it with another secured one. If you go Administration, Configuration, general and set the SMTP host and then do a GET on /api/settings/values?keys=email.smtp_host.secured you will get a response like this:

{
    "settings": [],
    "setSecuredSettings": [
        "email.smtp_host.secured"
    ]
}

So you know it is secured because the setSecuredSettings contains the key of the secured value. If you haven't set a value for this key then both sets of results will be empty - ie:

{
    "settings": [],
    "setSecuredSettings": []
}

Hope this helps

romainourgorry commented 1 year ago

Hello,

Any update on this new feature?

Thanks

smokedlinq commented 11 months ago

Should the existing resource be made to support it or should a new resource for secured settings be used since you won't be able to read the value, only create/update/delete ...

jdamata commented 11 months ago

Should the existing resource be made to support it or should a new resource for secured settings be used since you won't be able to read the value, only create/update/delete ...

Initially i imagined the existing resource to support secured settings and added the bug label. I think a new resource makes more sense to me now which is what you are hinting at i guess :)

smokedlinq commented 11 months ago

It would make it easier as you can't read the secrets. You could also make sure the value is a secret by default and not based on the caller having to configure it. It's the same calls for set/unset, just trimmed capabilities on the provider resource.

smokedlinq commented 11 months ago

If anyone wants a terraform_data resource using PowerShell 7.x command to do the same thing in the mean time ...

resource "terraform_data" "sonar_auth_saml_certificate" {
  input = azuread_service_principal_token_signing_certificate.this.value

  provisioner "local-exec" {
    interpreter = [
      "pwsh", "-NoLogo", "-NonInteractive", "-NoProfile", "-Command", 
      "$PSDefaultParameterValues['Invoke-RestMethod:Credential'] = [pscredential]::new('admin', (ConvertTo-SecureString -String $env:ADMIN_PASSWORD -AsPlainText -Force));",
      "$PSDefaultParameterValues['Invoke-RestMethod:Authentication'] = 'Basic';"
    ]
    environment = {
      HOST_NAME      = var.host_name
      ADMIN_PASSWORD = var.admin_password
      SETTING_KEY    = "sonar.auth.saml.certificate.secured"
      SETTING_VALUE  = "-----BEGIN CERTIFICATE----- ${azuread_service_principal_token_signing_certificate.this.value} -----END CERTIFICATE-----"
    }
    command = <<EOT
      Invoke-RestMethod -Method Post -Uri "https://$($env:HOST_NAME)/api/settings/set?key=$($env:SETTING_KEY)&value=$($env:SETTING_VALUE)"
EOT
  }
}
rendevor commented 6 months ago

Inspired by @smokedlinq my workaround:

variable "sonarqube_secure_settings" {
  type = map(string)
  default = {
    "sonar.auth.gitlab.applicationId.secured" = "app id"
    "sonar.auth.gitlab.secret.secured"        = "app token"
    "email.smtp_host.secured"                 = "corporate server"
  }
}
resource "terraform_data" "setup_secure_settings" {
  count = length(keys(var.sonarqube_secure_settings))

  provisioner "local-exec" {
    environment = {
      HOST_NAME = var.sonarqube_settings["sonar.core.serverBaseURL"]
    }
    command = <<EOT
      curl --header "Authorization: Bearer ${var.TERRAFORM_CONFIG_SONAR_TOKEN}" -X POST "$HOST_NAME/api/settings/set?key=${element(keys(var.sonarqube_secure_settings), count.index)}&value=${var.sonarqube_secure_settings[element(keys(var.sonarqube_secure_settings), count.index)]}"
    EOT
  }
}