{"id":20697453,"url":"https://github.com/epomatti/azure-sql-security","last_synced_at":"2025-08-30T20:15:09.849Z","repository":{"id":209225639,"uuid":"722806459","full_name":"epomatti/azure-sql-security","owner":"epomatti","description":"Azure SQL Database security features","archived":false,"fork":false,"pushed_at":"2025-01-27T21:17:25.000Z","size":136,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-11T02:51:12.703Z","etag":null,"topics":["azure","azure-security","cmk","elastic","elastic-pool","keyvault","mssql","pool","sql","sql-database","sql-server","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/epomatti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-24T02:07:22.000Z","updated_at":"2025-01-27T21:17:29.000Z","dependencies_parsed_at":"2023-11-26T00:21:45.896Z","dependency_job_id":"8efdbc1e-81b4-40fd-bfdc-9523fd255080","html_url":"https://github.com/epomatti/azure-sql-security","commit_stats":null,"previous_names":["epomatti/azure-sql-security"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/epomatti/azure-sql-security","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epomatti%2Fazure-sql-security","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epomatti%2Fazure-sql-security/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epomatti%2Fazure-sql-security/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epomatti%2Fazure-sql-security/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/epomatti","download_url":"https://codeload.github.com/epomatti/azure-sql-security/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epomatti%2Fazure-sql-security/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272900164,"owners_count":25012034,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-security","cmk","elastic","elastic-pool","keyvault","mssql","pool","sql","sql-database","sql-server","terraform"],"created_at":"2024-11-17T00:18:06.956Z","updated_at":"2025-08-30T20:15:09.825Z","avatar_url":"https://github.com/epomatti.png","language":"HCL","readme":"# Azure SQL Security\n\nImplementation of advanced SQL Server security features following [best practices][1].\n\nSet up the parameters:\n\n\u003e Edit the template and add your IP address\n\n```sh\ncp config/sample.tfvars .auto.tfvars\n```\n\nCreate the baseline infrastructure:\n\n```sh\nterraform init\nterraform apply -auto-approve\n```\n\nFollowing sections will expand on this infrastructure for hands-on practice.\n\n## Transparent Data Encryption (TDE)\n\nTDE is enabled on all new databases for Encryption-at-rest.\n\nThis sample database is configured with CMK, and for for this purpose enabling purge protection for the Key Vault is required.\n\nIt is important to notice that databases will default to the Server CMK, but it is possible to use a database-specific CMK.\n\n## Always Encrypted\n\nColumn-Level Security via column encryption.\n\nSecure enclaves [supported][2] are:\n\n- VBS (Virtual) 👈 We'll use this one.\n- SGX (Hardware)\n\nActivate the \"Always Encrypted\" functionality:\n\n```sh\naz sql db update -g rg-bigbank79 -s sqls-bigbank79 -n sqldb-bigbank79 --preferred-enclave-type VBS\n```\n\n\u003e For details on next steps check the official [documentation][3] tutorial.\n\nUsing **SSMS**, connect to the database with Always Encrypted **disabled**.\n\nCreate some data running the following files:\n\n1. [`tsql/schema.sql`](sql/schema.sql)\n2. [`tsql/data.sql`](sql/data.sql)\n\nNow create the Always Encrypted keys:\n\n\u003e Database Engine is [not involved][7] since the data has to be protected, so T-SQL cannot be used.\n\n1. CMK1 (Column master key)\n2. CEK1 (Column encryption key)\n\n\u003cimg src=\".assets/mssql-alwaysencrypted.png\" /\u003e\n\nThe Key Vaults keys should already be available for selection.\n\nReconnect to the database with Always Encrypted **enabled** (with Secure Enclaves, but no attestation).\n\nEncrypt the `SSN` and `Salary` columns:\n\n- [`tsql/encrypt.sql`](tsql/encrypt.sql)\n\nWithin the enabled session, it is possible to run [`rich queries`](tsql/richqueries.sql)\n\nNow, connect to a new session with Always Encrypt **disabled**.\n\nQuerying results from a disabled session will now show encrypted values:\n\n\u003cimg src=\".assets/mssql-alwaysencrypted-results.png\" /\u003e\n\n## Always Encrypted with T-SQL\n\nHere is a different [example][8] using T-SQL.\n\n```sql\nUSE database;\nGO\n\nCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P@ssw0rd.123';\n\nCREATE CERTIFICATE Certificate_key WITH SUBJECT = 'Protected my data';\n```\n\n## Row-Level Security\n\n[Row-Level Security][4] is a feature within SQL Server, but has a different mechanism than Column-Level Encryption.\n\n## Entra ID integration\n\nThis database will be integrated with Entra ID. The logged user will be the Entra ID Administrator.\n\n\u003e 💡 For Azure SQL Databases, mapping the Entra ID user to the Server is not supported, only directly to the database. But it is supported for Azure SQL Managed Instances.\n\u003e\n\u003e \"Contained\" database users are standalone only for the databases, but can reference External Providers such as Entra ID.\n\nTerraform will have created an additional user `sqldeveloper` on Entra ID to use in this example.\n\nFor Azure SQL Databases, we'll create a contained database user that is mapped to an Entra ID-based login:\n\n```sql\n--Create the contained DB User authenticated by AAD\nCREATE USER [sqldeveloper@\u003cTENANT\u003e.onmicrosoft.com] FROM EXTERNAL PROVIDER;\n\n--Add some permissions to the user\nALTER ROLE \"db_owner\" ADD MEMBER \"sqldeveloper@\u003cTENANT\u003e.onmicrosoft.com\";\n```\n\nConnect with the Entra ID user specifying the database.\n\n## Auditing\n\nDocumentation for [audit action groups \u0026 actions][5].\n\nDefault audit settings:\n\n\u003e The default auditing settings include the following set of action groups, which will audit all the queries and stored procedures executed against the database, as well as successful and failed logins:\n\u003e \n\u003e \n\u003e - BATCH_COMPLETED_GROUP\n\u003e - SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP\n\u003e - FAILED_DATABASE_AUTHENTICATION_GROUP\n\n## Ledger\n\nLedger is an option to verify data integrity.\n\nThis is not path for AZ-500 but will keep it here for reference.\n\n## Data Classification\n\nThe database will be created using `SQL Information Protection` policy.\n\n\u003e It is possible to use `Microsoft Information Protection` to fetch sensitivity labels defined in Microsoft 365.\n\nAfter creating the schema, classify the data:\n\n```sh\naz sql db classification update -g rg-bigbank79 -s sqls-bigbank79 -n sqldb-bigbank79 --column FirstName --schema HR --table Employees --information-type Name --label General\naz sql db classification update -g rg-bigbank79 -s sqls-bigbank79 -n sqldb-bigbank79 --column LastName --schema HR --table Employees --information-type Name --label General\naz sql db classification update -g rg-bigbank79 -s sqls-bigbank79 -n sqldb-bigbank79 --column SSN --schema HR --table Employees --information-type SSN --label Confidential\naz sql db classification update -g rg-bigbank79 -s sqls-bigbank79 -n sqldb-bigbank79 --column Salary --schema HR --table Employees --information-type Financial --label \"Highly Confidential\"\n```\n\n\u003cimg src=\".assets/mssql-classification.png\" /\u003e\n\n## Dynamic Data Masking\n\nDynamic Data Masking can be applied from within or outside the database.\n\nCheck the [documentation][6] for details.\n\n## Elastic Pools\n\nTo create an Elastic Pool, set:\n\n```terraform\nmssql_create_elastic_pool = true\n```\n\nAdd the database to the elastic pool using the portal. The SKU of the database will be set as `ElasticPool`.\n\nTo enable `Always Encrypted` for the elastic pool, do it so manually.\n\n\n[1]: https://learn.microsoft.com/en-us/sql/relational-databases/security/sql-server-security-best-practices?view=sql-server-ver16\n[2]: https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/always-encrypted-enclaves?view=sql-server-ver16#supported-enclave-technologies\n[3]: https://learn.microsoft.com/en-us/azure/azure-sql/database/always-encrypted-enclaves-getting-started-vbs?view=azuresql\u0026tabs=ssmsrequirements%2Cazure-cli\n[4]: https://learn.microsoft.com/en-us/sql/relational-databases/security/row-level-security?view=sql-server-ver16\n[5]: https://learn.microsoft.com/en-us/sql/relational-databases/security/auditing/sql-server-audit-action-groups-and-actions?view=sql-server-ver16\n[6]: https://learn.microsoft.com/en-us/sql/relational-databases/security/dynamic-data-masking?view=sql-server-ver16\n[7]: https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/always-encrypted-database-engine?view=sql-server-ver15\n[8]: https://www.sqlshack.com/an-overview-of-the-column-level-sql-server-encryption/?_ga=2.188209896.1510144942.1703251968-967359652.1700361706\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepomatti%2Fazure-sql-security","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fepomatti%2Fazure-sql-security","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepomatti%2Fazure-sql-security/lists"}