Seguridad con PowerShell
Haremos uso de 3 ficheros:
- El script principal de ejecución: PS_Lab03_Seguridad.ps1.
- Fichero de módulo de script con diferentes funciones que usaremos en el script principal: Funciones.psm1.
- Un fichero de configuración donde están la seguridad: Seguridad.cfg.
Nuestro fichero de configuración tendrá el siguiente contenido:
SQL_SERVER = SRVPRO SQL_Database = BD SQL_Table = SECURITY
La gestión de la seguridad la tenemos registrada en tablas de BD, en el script principal consultaremos las tablas y obtendremos la información de usuarios y países para este ejemplo, de tal forma que el roleado del cubo lo gestionaremos en base a esta información.
Veamos ahora paso por paso el fichero principal:
Establecemos variables de inicio (Parámetros).
$pRutaFicheroParam = "C:\Users\Administrador\Documents\PowerShell\Config\Seguridad.cfg"
Cargamos un array con los datos de los parametros del fichero pRutaFicheroParam:
$ConfigParam = @{} # Tabla de hash para guardar los pares Parametro - Valor
Get-Content $pRutaFicheroParam | foreach {
$line = $_.split("=")
$ConfigParam.($line[0].Trim()) = $line[1]
}
Establecemos rutas donde leer los ficheros:
$FicheroModulo="C:\Users\Administrador\Documents\PowerShell\Funciones.psm1"
Cargamos el modulo que contiene las funciones auxiliares:
$LoadedModule = Import-Module $FicheroModulo -PassThru -force -DisableNameChecking
Cargamos la libreria de funciones de analysis services:
ImportModulesAndAssemblies
Creamos un objeto de tipo Server:
$ASObj = New-Object Microsoft.AnalysisServices.Server
Creamos los objetos de base de datos SSAS:
$ASObj.Connect($ConfigParam.SSAS_Server)
$ASDataBase = $ASObj.Databases.Find($ConfigParam.SSAS_Database)
#-----------------------------------------------------------------------------
LogWriteSeparador
LogWrite -Text "Conexion establecida con el servidor de analysis services:........." , ($ConfigParam.SSAS_Server + " --> " + $ASDataBase.name), " [Ok]" -Color White, Yellow, Green
Conectamos con el sql server donde se almacena la relación de permisos:
$dataSource = $ConfigParam.SQL_SERVER
$database = $ConfigParam.SQL_Database
$connectionString = “Server=$dataSource;Database=$database;Integrated Security=True;”
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
LogWrite -Text "Conexion establecida con el servidor de SQl Server:................" , ($ConfigParam.SQL_SERVER + " --> " + $connection.DataBase.ToString()), " [Ok]" -Color White, Yellow, Green
LogWriteSeparador
Cargamos los datos de la tabla que contiene la información de seguridad:
$queryCountries = “SELECT [Country] FROM [dbo].[" + $ConfigParam.SQL_Table + "] Group by [Country]”
$queryUsers = "SELECT [UserName] ,[Country] ,[MemberUN] FROM [dbo].[" + $ConfigParam.SQL_Table + "]"
#Paises
$commandCountries = $connection.CreateCommand()
$commandCountries.CommandText = $queryCountries
$result = $commandCountries.ExecuteReader()
$tableCountries = new-object System.Data.DataTable
$tableCountries.Load($result)
#Usuarios
$commandUsers = $connection.CreateCommand()
$commandUsers.CommandText = $queryUsers
$result = $commandUsers.ExecuteReader()
$tableUsers = new-object System.Data.DataTable
$tableUsers.Load($result)
LogWrite -Text "Se han leido correctamente los datos de seguridad, se comprobaran los siguientes roles: " , ($tableCountries.Rows | ForEach-Object {"[" + $_.Country + "] "}) -Color White, Yellow
LogWriteSeparador
Mediante un bucle vamos recorriendo la consulta de países y asignando el rol correspondiente a cada usuario, también se realiza un borrado previo de los roles en caso de que ya exista, esto lo hacemos para que si a un país se le ha modificado la asignación de usuarios que tiene, refrescamos el rol con la nueva información de la tabla:
Foreach ($RowCountry in $tableCountries.Rows)
{
$rolename = $RowCountry.country
#Borramos el rol si ya existe
$roleToDelete = $ASDataBase.Roles.FindByName($roleName)
if ($roleToDelete)
{
$roleToDelete.Drop(“AlterOrDeleteDependents”)
LogWrite -Text " Se ha borrado el rol ", ("[" + $roleName + "]"), " para su recreacion" -Color white, yellow, white
}
#Creamos un objeto de tipo Rol con el nombre del pais al que concede permisos
[Microsoft.AnalysisServices.Role] $roleToCreate = new-Object([Microsoft.AnalysisServices.Role])($rolename)
#Le añadimos los usuarios pertenecientes a ese rol
$Users = $tableUsers | Where {$_.Country -eq $RowCountry.country}
Foreach ( $User in $Users)
{
$ExecuteResult = $roleToCreate.Members.Add($User.Username)
}
#Añadimos el rol a la base de datos y le damos permisos de lectura
$ExecuteResult = $ASDataBase.Roles.Add($roleToCreate)
$roleToCreate.Update()
$dbperm = $ASDataBase.DatabasePermissions.Add($roleToCreate.ID)
$dbperm.Read = [Microsoft.AnalysisServices.ReadAccess]::Allowed
$dbperm.Update()
#Añadimos Permisos de lectura a los cubos de la base de datos
foreach ($cube in $ASDataBase.Cubes)
{
$cubeperm = $cube.CubePermissions.Add($roleToCreate.ID)
$cubePerm.Read = [Microsoft.AnalysisServices.ReadAccess]::Allowed
$cubeperm.Update()
}
#Localizamos la dimension geografia por la que estableceremos los permisos
$dim = $ASDataBase.Dimensions.FindByName(“Geography”)
#Añadimos permisos en la dimension
$ExecuteResult = $dim.DimensionPermissions.Add($roleToCreate.ID)
$dimperm = $dim.DimensionPermissions.add($roleToCreate.ID)
$dimperm.Read = [Microsoft.AnalysisServices.ReadAccess]::Allowed
#Localizamos el atributo pais por el que estableceremos los permisos
$att = $dim.Attributes.FindByName(“Country”)
#Añadimos permisos al atributo
$attPerm = $dimPerm.AttributePermissions.Add($att.ID)
$attPerm.AllowedSet = “{[Geography].[Country].&[” + $RowCountry.country + “]}”
$dimPerm.Update()
LogWrite -Text " Se han ha creado el Rol: " ,("[" + $roleName + "]") , " con los siguientes usuarios asociados: " , ($Users | ForEach-Object {"[" + $_.UserName + "] "}) -Color White, Yellow, white, Yellow
}
LogWriteSeparador
A modo de resumen de este hilo de código, veamos una diagrama de flujo de los pasos seguidos, por supuesto lo podemos complicar tanto como deseemos:
Con lo visto hasta aquí tendríamos lista la parte de seguridad y damos por cerrado el post con la parte de automatización de la seguridad de SSAS.
