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.