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.