Skip to content

Commit

Permalink
Merge pull request #4754 from bgs113/master
Browse files Browse the repository at this point in the history
azurerm_sql_server: Enable SystemAssigned identity
  • Loading branch information
tombuildsstuff authored Oct 30, 2019
2 parents 1eb864e + da08b94 commit e44c0db
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 0 deletions.
25 changes: 25 additions & 0 deletions azurerm/data_source_sql_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,27 @@ func dataSourceSqlServer() *schema.Resource {
Computed: true,
},

"identity": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Computed: true,
},
"principal_id": {
Type: schema.TypeString,
Computed: true,
},
"tenant_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},

"tags": tags.SchemaDataSource(),
},
}
Expand Down Expand Up @@ -83,5 +104,9 @@ func dataSourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error
d.Set("administrator_login", props.AdministratorLogin)
}

if err := d.Set("identity", flattenAzureRmSqlServerIdentity(resp.Identity)); err != nil {
return fmt.Errorf("Error setting `identity`: %+v", err)
}

return tags.FlattenAndSet(d, resp.Tags)
}
61 changes: 61 additions & 0 deletions azurerm/resource_arm_sql_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,31 @@ func resourceArmSqlServer() *schema.Resource {
Computed: true,
},

"identity": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"SystemAssigned",
}, false),
},
"principal_id": {
Type: schema.TypeString,
Computed: true,
},
"tenant_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},

"tags": tags.Schema(),
},
}
Expand Down Expand Up @@ -115,6 +140,11 @@ func resourceArmSqlServerCreateUpdate(d *schema.ResourceData, meta interface{})
},
}

if _, ok := d.GetOk("identity"); ok {
sqlServerIdentity := expandAzureRmSqlServerIdentity(d)
parameters.Identity = sqlServerIdentity
}

if d.HasChange("administrator_login_password") {
adminPassword := d.Get("administrator_login_password").(string)
parameters.ServerProperties.AdministratorLoginPassword = utils.String(adminPassword)
Expand Down Expand Up @@ -173,6 +203,10 @@ func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error {
d.Set("location", azure.NormalizeLocation(*location))
}

if err := d.Set("identity", flattenAzureRmSqlServerIdentity(resp.Identity)); err != nil {
return fmt.Errorf("Error setting `identity`: %+v", err)
}

if serverProperties := resp.ServerProperties; serverProperties != nil {
d.Set("version", serverProperties.Version)
d.Set("administrator_login", serverProperties.AdministratorLogin)
Expand Down Expand Up @@ -202,3 +236,30 @@ func resourceArmSqlServerDelete(d *schema.ResourceData, meta interface{}) error

return future.WaitForCompletionRef(ctx, client.Client)
}

func expandAzureRmSqlServerIdentity(d *schema.ResourceData) *sql.ResourceIdentity {
identities := d.Get("identity").([]interface{})
if len(identities) == 0 {
return &sql.ResourceIdentity{}
}
identity := identities[0].(map[string]interface{})
identityType := sql.IdentityType(identity["type"].(string))
return &sql.ResourceIdentity{
Type: identityType,
}
}
func flattenAzureRmSqlServerIdentity(identity *sql.ResourceIdentity) []interface{} {
if identity == nil {
return []interface{}{}
}
result := make(map[string]interface{})
result["type"] = identity.Type
if identity.PrincipalID != nil {
result["principal_id"] = identity.PrincipalID.String()
}
if identity.TenantID != nil {
result["tenant_id"] = identity.TenantID.String()
}

return []interface{}{result}
}
85 changes: 85 additions & 0 deletions azurerm/resource_arm_sql_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)
Expand Down Expand Up @@ -120,6 +121,68 @@ func TestAccAzureRMSqlServer_withTags(t *testing.T) {
})
}

func TestAccAzureRMSqlServer_withIdentity(t *testing.T) {
resourceName := "azurerm_sql_server.test"
ri := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMSqlServerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMSqlServer_withIdentity(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlServerExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "identity.0.type", "SystemAssigned"),
resource.TestMatchResourceAttr(resourceName, "identity.0.principal_id", validate.UUIDRegExp),
resource.TestMatchResourceAttr(resourceName, "identity.0.tenant_id", validate.UUIDRegExp),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"administrator_login_password"},
},
},
})
}

func TestAccAzureRMSqlServer_updateWithIdentityAdded(t *testing.T) {
resourceName := "azurerm_sql_server.test"
ri := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMSqlServerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMSqlServer_basic(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlServerExists(resourceName),
),
},
{
Config: testAccAzureRMSqlServer_withIdentity(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlServerExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "identity.0.type", "SystemAssigned"),
resource.TestMatchResourceAttr(resourceName, "identity.0.principal_id", validate.UUIDRegExp),
resource.TestMatchResourceAttr(resourceName, "identity.0.tenant_id", validate.UUIDRegExp),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"administrator_login_password"},
},
},
})
}

func testCheckAzureRMSqlServerExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
// Ensure we have enough information in state to look up in API
Expand Down Expand Up @@ -276,3 +339,25 @@ resource "azurerm_sql_server" "test" {
}
`, rInt, location, rInt)
}

func testAccAzureRMSqlServer_withIdentity(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_sql_server" "test" {
name = "acctestsqlserver%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
version = "12.0"
administrator_login = "mradministrator"
administrator_login_password = "thisIsDog11"
identity {
type = "SystemAssigned"
}
}
`, rInt, location, rInt)
}
12 changes: 12 additions & 0 deletions website/docs/d/sql_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@ output "sql_server_id" {

* `administrator_login` - The administrator username of the SQL Server.

* `identity` - An `identity` block as defined below.

* `tags` - A mapping of tags assigned to the resource.

---

An `identity` block exports the following:

* `principal_id` - The ID of the Principal (Client) in Azure Active Directory.

* `tenant_id` - The ID of the Azure Active Directory Tenant.

* `type` - The identity type of the SQL Server.
20 changes: 20 additions & 0 deletions website/docs/r/sql_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,35 @@ The following arguments are supported:

* `administrator_login_password` - (Required) The password associated with the `administrator_login` user. Needs to comply with Azure's [Password Policy](https://msdn.microsoft.com/library/ms161959.aspx)

* `identity` - (Optional) An `identity` block as defined below.

* `tags` - (Optional) A mapping of tags to assign to the resource.

---

An `identity` block supports the following:

* `type` - (Required) Specifies the identity type of the SQL Server. At this time the only allowed value is `SystemAssigned`.

~> **NOTE:** The assigned `principal_id` and `tenant_id` can be retrieved after the identity `type` has been set to `SystemAssigned` and the SQL Server has been created. More details are available below.

## Attributes Reference

The following attributes are exported:

* `id` - The SQL Server ID.
* `fully_qualified_domain_name` - The fully qualified domain name of the Azure SQL Server (e.g. myServerName.database.windows.net)

---

`identity` exports the following:

* `principal_id` - The Principal ID for the Service Principal associated with the Identity of this SQL Server.

* `tenant_id` - The Tenant ID for the Service Principal associated with the Identity of this SQL Server.

-> You can access the Principal ID via `${azurerm_sql_server.test.identity.0.principal_id}` and the Tenant ID via `${azurerm_sql_server.test.identity.0.tenant_id}`

## Import

SQL Servers can be imported using the `resource id`, e.g.
Expand Down

0 comments on commit e44c0db

Please sign in to comment.