Created
September 24, 2020 12:54
-
-
Save mrjamiebowman/ced0d015b3bcdd52a59056678e74d60f to your computer and use it in GitHub Desktop.
.NET Health Check SQL Permissions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SqlPermsHealthCheck : IHealthCheck | |
{ | |
private string sql = @"SELECT | |
p.name, | |
p.schema_id, | |
schema_name = sch.name, | |
has_perms_by_name(p.name, 'OBJECT', 'EXECUTE') as has_execute, | |
has_perms_by_name(p.name, 'OBJECT', 'VIEW DEFINITION') as has_view_definition | |
FROM sys.procedures p | |
LEFT JOIN sys.schemas sch ON sch.schema_id = p.schema_id | |
WHERE p.type = 'P'"; | |
public string ConnectionString { get; set; } | |
public List<HealthCheckSqlPermission> SqlPerms { get; set; } = new List<HealthCheckSqlPermission>(); | |
public SqlPermsHealthCheck(string connectionString) | |
{ | |
ConnectionString = connectionString; | |
} | |
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) | |
{ | |
bool? healthCheckResultHealthy = null; | |
var data = new ConcurrentDictionary<string, object>(); | |
// verify connection string | |
if (String.IsNullOrWhiteSpace(ConnectionString)) | |
throw new ArgumentException("Connection string is not set."); | |
// get stored procs and perms from db | |
using (SqlConnection connection = new SqlConnection(ConnectionString)) | |
{ | |
// Create a SqlCommand object. | |
using (SqlCommand sqlCommand = new SqlCommand(sql, connection)) | |
{ | |
try | |
{ | |
connection.Open(); | |
// Run the query by calling ExecuteReader(). | |
using (SqlDataReader dataReader = sqlCommand.ExecuteReader()) | |
{ | |
// Create a data table to hold the retrieved data. | |
DataTable dataTable = new DataTable(); | |
// Load the data from SqlDataReader into the data table. | |
dataTable.Load(dataReader); | |
foreach (DataRow row in dataTable.Rows) | |
{ | |
HealthCheckSqlPermission model = new HealthCheckSqlPermission(); | |
model.name = row["name"].ToString(); | |
model.schema_id = row["schema_id"].ToString(); | |
model.schema_name = row["schema_name"].ToString(); | |
model.has_execute = Convert.ToBoolean(row["has_execute"]); | |
model.has_view_definition = Convert.ToBoolean(row["has_view_definition"]); | |
SqlPerms.Add(model); | |
} | |
// Close the SqlDataReader. | |
dataReader.Close(); | |
} | |
} | |
catch (Exception ex) | |
{ | |
healthCheckResultHealthy = false; | |
data.TryAdd("error", "connection failure."); | |
goto handleresult; | |
} | |
finally | |
{ | |
// Close the connection. | |
connection.Close(); | |
} | |
} | |
} | |
// get degraded | |
var degradedPerms = SqlPerms.Where(x => x.has_view_definition == false || x.has_execute == false); | |
// handle result | |
if (degradedPerms.Count() == 0 && healthCheckResultHealthy == null) | |
{ | |
healthCheckResultHealthy = true; | |
} | |
else | |
{ | |
// return degraded | |
foreach (var perm in degradedPerms) | |
{ | |
data.TryAdd("degraded", $"{perm.schema_name}.{perm.name}"); | |
} | |
} | |
handleresult: | |
// return health check | |
if (healthCheckResultHealthy == true) | |
{ | |
data.TryAdd("status", "UP"); | |
var health = HealthCheckResult.Healthy("A healthy result.", data); | |
return Task.FromResult(health); | |
} | |
else | |
{ | |
data.TryAdd("status", "DEGRADED"); | |
var health = HealthCheckResult.Degraded("An unhealthy result.", null, data); | |
return Task.FromResult(health); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI.. WIP