Monday, November 23, 2009

VBScript: manejo de cadenas de texto

VBScript: manejo de cadenas de texto



Algunas de las funciones más habituales para manipular cadenas de texto son:


Function
Description
InStr
Returns the position of the first occurrence of
one string within another. The search begins at the first character of the
string
InStrRev
Returns the position of the first occurrence of one string
within another. The search begins at the last character of the string
LCase
Converts a specified string to lowercase
Left
Returns a specified number of characters from
the left side of a string
Len
Returns the number of characters in a string
LTrim
Removes spaces on the left side of a string
RTrim
Removes spaces on the right side of a string
Trim
Removes spaces on both the left and the right side of a
string
Mid
Returns a specified number of characters from a
string
Replace
Replaces a specified part of a string with another string a
specified number of times
Right
Returns a specified number of characters from
the right side of a string
Space
Returns a string that consists of a specified number of
spaces
StrComp
Compares two strings and returns a value that represents
the result of the comparison
String
Returns a string that contains a repeating character of a
specified length
StrReverse
Reverses a string
UCase
Converts a specified string to uppercase

(la fuente es: http://www.w3schools.com/VBscript/vbscript_ref_functions.asp)


A menudo, los ficheros que procesamos tienen líneas con varios campos delimitados por algún tipo de carácter. Todos los lenguajes de programación/scripting poseen algun método para procesar cadenas divididas en campos. En VBScript esta función es:

Split(expression[,delimiter[,count[,compare]]])


La descripción de sus parámetros tal y como la muestran en
http://www.w3schools.com/VBscript/func_split.asp

Parameter
Description
expression
Required. A string expression that contains substrings
and delimiters
delimiter
Optional. A string character used to identify substring
limits. Default is the space character
count
Optional. The number of substrings to be returned. -1
indicates that all substrings are returned
compare
Optional. Specifies the string comparison to use.
Can
have one of the following values:

  • 0 = vbBinaryCompare - Perform a binary comparison
  • 1 = vbTextCompare - Perform a textual comparison

Ejemplo de uso:

Se trata de un script que comprueba la existencia de un fichero de texto, y si existe lo abre y lo recorre línea a línea procesando cada una de ellas. Las líneas contienen campos separados por ";" y el script nos muestra primero la línea y a continuación los campos que contiene.

dim oshell
dim fich, fs

'ubicación del fichero de altas
nombre_fich="c:\tmp\altas.txt"

set oshell=createobject("WScript.shell")
set fs=createobject("scripting.FileSystemObject")

'comprobamos que exista el fichero de altas
if not fs.FileExists(nombre_fich) then
  wscript.echo "no existe el fichero "& nombre_fich
  WScript.Quit 4
end if

'Si hemos llegado hasta aquí es que existe y lo abrimos
set fich=fs.OpenTextFile (nombre_fich, 1, "True" )

'Lo recorremos
Do While fich.atEndOfStream <> True
  linea=fich.ReadLine
' Ahora mostramos la línea leída
  wscript.echo linea
' Parseamos los campos
  campos = split(linea,";")
  for each a in campos
    wscript.echo "valor del campo: "&a
  next
Loop

fich.close



Evidentemente, podríamos hacer algo más útil que mostrar la línea, como por ejemplo usar un objeto de tipo shell para ejecutar dsadd user <usuario> -memberof <grupos>

Sunday, November 22, 2009

VBScript: trabajando con ficheros (II)

VBScript: trabajando con ficheros (II)


Microsoft proporciona mediante FSO una herramienta para trabajar con carpetas y ficheros.

Microsoft se refiere a FileSystemObject como a un "Object Model", esto puede entenderse como sinónimo de clase. Así, FSO es una clase mediante la cual se puede trabajar con ficheros y carpetas. Esta clase está en la librería de nombre "Scripting", que está en la dll: Scrrun.dll.

En la sesión anterior abrimos un fichero para leer su contenido y recorrimos su contenido línea a línea.

En la siguiente dirección hay una lista de los métodos que proporciona esta clase:

http://msdn.microsoft.com/en-us/library/aa711216(VS.71).aspx

y aquí está la lista, cada nombre de función es un link a una página con una explicación detallada con un ejemplo:



BuildPath Method

This method is used to append a name onto an existing path.


[newfullpath = ]object.BuildPath(path, name)




CopyFile Method

This method allows us to copy one or more files from one location (the source) to another (destination).


Syntax: object.CopyFile source, destination [, overwrite]




CopyFolder Method

Copies one or more folders and all contents, including files and subfolders, from one location to another.


Syntax: object.CopyFolder source, destination, [, overwrite]



CreateFolder Method

This method allows us to create a folder.


Syntax: object.CreateFolderfoldername




CreateTextFile Method

Creates a text file and returns a TextStreamObject that can then be used to write to and read from the file.


Syntax: object.CreateTextFile
filename [, overwrite[, unicode]]





DeleteFile Method

This method deletes a specified file or files (using wilcards).


Syntax: object.DeleteFile
file [, force]




DeleteFolder Method

This method deletes a specified folder, including all files and subfolders.


Syntax: object.DeleteFolder
folder [, force]




DriveExists Method

This method lets us check if a specified drive exists. It returns True if the drive does exist and False if it doesn't.


Syntax: object.DriveExists(drive)



FileExists Method

Lets us check whether a specified file exists. Returns True if the file does exist and False otherwise.


Syntax: object.FileExists(file)



FolderExists Method

Allows us to check if a specified folder exists. Returns True if the folder does exist and False if it doesn't.


Syntax: object.FolderExists(folder)



GetAbsolutePathName Method

This method gets the complete path from the root of the drive for the specified path string.


Syntax: object.GetAbsolutePathName(path)



GetBaseName Method

This method gets the base name of the file or folder in a specified path.


Syntax: object.GetBaseName(path)



GetDrive Method

This method returns a Drive object corresponding to the drive in a supplied path.


Syntax: object.GetDrive(drive)



GetDriveName Method

This method gets a string containing the name of the drive in a supplied path.


Syntax: object.GetDriveName(path)



GetExtensionName Method

Used to return a string containing the extension name of the last component in a supplied path.


Syntax: object.GetExtensionName(path)



GetFile Method

Returns the File object for the specified file name.


Syntax: object.GetFile(filename)



GetFileName Method

This method is used to return the name of the last file or folder of the supplied path.


Syntax: object.GetFileName(path)



GetFileVersion Method

This method is used to return the version of the file in the
specified path.



Syntax: object.GetFileVersion(path)



GetFolder Method

This method returns a Folder object of the folder specified in the folder parameter.


Syntax: object.GetFolder(folder)



GetParentFolderName Method

Returns a string containing the name of the parent folder of the last file or folder in a specified path.


Syntax: object.GetParentFolderName(path)



GetSpecialFolder Method

Returns the path to one of the special folders - \Windows, \System or \TMP.


Syntax: object.GetSpecialFolder(folder)



GetTempName Method

This method is used to generate a random filename for a temporary file..


Syntax: object.GetTempName



MoveFile Method

Moves one or more files from one location to another.


Syntax: object.MoveFile source, destination



MoveFolder Method

Moves one or more folders from one location to another.


Syntax: object.MoveFolder source, destination



OpenTextFile Method

Opens the file specified in the filename parameter and returns an instance of the TextStreamObject for that file.


Syntax: object.OpenTextFile(filename [, iomode[, create[, format]]])










Friday, November 20, 2009

VBScript: empezando a trabajar con fi...

VBScript: empezando a trabajar con ficheros (I)




Si para ejecutar otros programas usábamos un objeto de tipo WScript.shell, para acceder al sistema de ficheros usamos un objeto de tipo FileSystemObject.

Podemos abrir ficheros con uno de sus métodos:
OpenTextFile
OpenAsTextStream

Para abrir un fichero de texto abretxt.vbs:

dim fso
dim fich
set fso=createobject("Scripting.FileSystemObject")
set fich=fso.OpenTextFile("c:\altas.txt")


Los ficheros se pueden abrir:
ForReading    1
ForWriting    2
ForAppending    8


Un fichero además se puede abrir con la codificación UTF, ASCII o la codificación por defecto, eso lo controlamos mediante las constantes:
UTF: TristateTrue -1
ASCII: TristateFalse -2
Default: TristateUseDefault 0

Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Const TristateUseDefault = -2
Const TristateTrue = -1
Const TristateFalse = 0
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile("D:\data\log.txt", ForWriting, True, TristateFalse)



Ahora vamos a ir leyendo una a una las líneas de un fichero d:\altas.txt:

Const ForReading = 1
Const TristateFalse = 0

Set fs = CreateObject("Scripting.FileSystemObject")
Set fich = fs.OpenTextFile("D:\\altas.txt", ForReading, "True")
Do While fich.atEndOfStream <> True
  linea=fich.ReadLine
' Ahora mostramos la línea leída
  wscript.echo linea
Loop

fich.close








VBScript: acceso a variables de sistema y ejecución de otros prog

VBScript: acceso a variables de sistema y ejecución de otros programas



Acceso a variables de sistema

VBScript proporciona acceso a las variables de sistema mediante el método ExpandEnvironmentStrings() de los objetos de tipo WScript.Shell.

La manera de obtener el valor de una variable es:
'Obtener una variable de tipo "WScript.shell"
set ws=createobject("WScript.shell")
'Obtener el valor de la variable de sistema que nos interese
'mediante la función ExpandEnvironmentStrings()
variable=ws.ExpandEnvironmentStrings("COMPUTERNAME")

'Ahora ya podemos hacer lo que sea con ese valor



Variable
Descripción
Ejemplo
COMMONPROGRAMFILESUbicación de la carpeta common program files
C:\Program files\Common Files
COMPUTERNAMENombre del equipo
PC2
COMSPECRuta completa hasta el actual cmd.exe
C:\Windows\system32\cmd.exe
HOMEDRIVEDisco en que está el perfil del usuario que ejecuta el script
C:
HOMEPATHUbicación de la raíz
\
LOGONSERVERNombre del servidor que validó al usuario
\\DC1
NUMBER_OF_PROCESSORSNumero de CPUs del equipo

OS
Nombre del S.O.
Window_NT
PATH
Rutas en que busca por defecto

PATHEXT
Extensiones que reconoce como de ejecutables
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;
PROCESSOR_ARCHITECTUREArquitectura de los procesadores
X86
SYSTEMDRIVEDisco de sistema
C:
SYSTEMROOTRaíz de la instalación de Windows
C:\WINNT
USERDOMAINDominio del usuario
LASALLE
USERNAME
Nombre del usuario
Steve Ballmer
USERPROFILE
Ruta del perfil de usuario
D:\Documents and Settings\Steve Ballmer


Ejecución de otros programas desde VBScript


Para ejecutar una aplicación en WSH hay que crear una instancia de  WScript.Shell, y entonces usar run().  Por ejemplo, para hacer un script que añada un usuario que pasamos por parámetro a nuestro script altas.vbs:

dim oshell

set oshell=createobject("WScript.shell")
oshell.run "dsadd user "& Chr(34) & "cn=jana montana,cn=users,dc=lasalle,dc=local"& Chr(34) & " -pwd P@@ssw0rd"


y en la OU users del dominio en cuestión aparecería el nombre de usuario en cuestión.
Chr(34) es la forma de escribir unas comillas que van dirigidas al parámetro de run() y no al VBScript. Lo que queremos que ejecute en realidad el script cuando lo llamamos como altas.vbs "jana montana" es:

dsadd user "cn=jana montana,cn=users,dc=lasalle,dc=local" -pwd P@@ssw0rd

ya que sin las comillas, dsadd dará un error al detectar un espacio entre jana y montana.

También podemos usar variables de sistema al llamar a run(). El siguiente ejemplo se encarga de abrir con el notepad el fichero que pasemos por parámetro:

dim oshell
set oshell=createobject("WScript.shell")
oshell.run "%SystemRoot%\system32\notepad "& wscript.arguments(0)


Parámetros adicionales para la función run():

Hasta ahora hemos tomado un objeto de tipo WScript.shell y hemos ejecutado run() pasándole como único argumento el nombre o ruta completa del programa que queríamos ejecutar. El método run() admite no obstante dos parámetros más, uno para controlar el comportamiento de la ventana en que se ejecutará el programa al que llamamos, y otro para controlar si el script debe esperar a que finalice el programa que acabamos de lanzar, o si puede seguir con la siguiente instrucción mientras se va ejecutando el programa que hemos lanzado.

object.Run (“command”, [winStyle], [“waitOnReturn”])

winStyle puede tomar valores entre 0 y 10. En el siguiente artículo de microsoft hay una descripción muy extensa: http://technet.microsoft.com/en-us/library/ee156605.aspx












 Integer 



                  Window Style Description



0



Hides the window and activates another window.



1



Activates and displays a window. If the window is minimized or
maximized, the system restores it to its original size and position. An
application should specify this flag when displaying the window for the
first time.



2



Activates the window and displays it as a minimized window.



3



Activates the window and displays it as a maximized window.



4



Displays a window in its most recent size and position. The active window remains active.



5



Activates the window and displays it in its current size and position.



6



Minimizes the specified window and activates the next top-level
window in the Z order. The Z order is nothing more than the list
detailing the order in which windows are to be activated. If you press
ALT+TAB, you will see a graphical representation of the Z list.



7



Displays the window as a minimized window. The active window remains active.



8



Displays the window in its current state. The active window remains active.



9



Activates and displays the window. If the window is minimized or
maximized, the system restores it to its original size and position. An
application should specify this flag when restoring a minimized window.



10



Sets the show-state based on the state of the program that started the application.


Si fijamos el valor de  waitOnReturn a True, el script vbs esperará a que finalice la ejecución que le acabamos de pedir antes de proseguir con la siguiente instrucción.















Monday, November 16, 2009

VBScript: procedimientos y otras curi...

VBScript: procedimientos y otras curiosidades


Procedimientos


Los procedimientos son un mecanismo para la reutilización de código, y también para su simplificación.

Visual Basic Script tiene tres tipos de procedimiento para favorecer la reutilización de código:
  1. subrutinas: ejecutan algo y ya está (p.e. borrar un directorio). Los parámetros se le pasan sin paréntesis.
  2. funciones: ejecutan algo y devuelven un valor(p.e. borrar un directorio y devolver true si se ha borrado correctamente, y false en cualquier otro caso). Los parámetros se le pasan entre paréntesis.
  3. eventos: son un tipo especial de subrutina que se ejecuta cuando se da una determinada condición como p.e. pulsar un botón o pasar por encima de un texto.


Ejemplo de función:

WScript.Echo “Has introducido el nombre “ & getName()



Function getName()
  Dim tmpName
  tmpName = “”
  Do While tmpName = “”
    tmpName = InputBox(“Introduce un nombre: ”)
  Loop
  getName = tmpName
End Function

(también existe:  Exit Function )


Ejemplo de subrutina:

showError "No se ha podido crear el fichero, compruebe que tiene permisos","Error de ejecución"

Sub showError(errorMessage,title)
  MsgBox “Input Error: “ & errorMessage,, title
End Sub




Información útil acerca del propio script o de su entorno

Alguna información útil que podemos recabar del script puede ser: la ruta completa desde la que se ejecuta, el nombre del script mismo, los argumentos que le hemos pasado.

los argumentos que le hemos pasado:
Set theArgs = WScript.Arguments

la ruta completa de ejecución:
WScript.ScriptFullName

el nombre del script:
WScript.ScriptName

Ejemplo de uso:

wscript.echo wscript.ScriptFullName
wscript.echo wscript.scriptname
wscript.echo wscript.arguments.count
for each elemento in wscript.arguments
 wscript.echo cstr(elemento)
next

La ruta completa de ejecución suele ser útil para poder acceder a ficheros de configuración o de datos que estén en el mismo directorio que nuestro script.






VBScript: estructuras de control de f...

VBScript: estructuras de control de flujo



Este texto es sólo una referencia, un lugar donde consultar cuando no recuerdes cómo se hacía un if, ...

El que quiera algo más trascendente: www.google.es y está lleno de sitios dónde se lo ofrecerán.


Condicional:

if ...then ...ElseIf...Else
currValue = 5
If currValue < 0 Then
  WScript.Echo “The value is less than zero.”
ElseIf currValue = 0 Then
  WScript.Echo “The value is equal to zero.”
ElseIf currValue = 1 Then
  WScript.Echo “The value is equal to one.”
ElseIf currValue = 2 Then
  WScript.Echo “The value is equal to two.”
ElseIf currValue = 3 Then
  WScript.Echo “The value is equal to three.”
ElseIf currValue = 4 Then
  WScript.Echo “The value is equal to four.”
ElseIf currValue = 5 Then
  WScript.Echo “The value is equal to five.”
Else
  WScript.Echo “Value doesn’t match expected parameters.”
End If


Select ... case

currValue = 9
Select Case currValue
Case currValue < 0
  WScript.Echo “The value is less than zero.”
Case 0
  WScript.Echo “The value is equal to zero.”
Case 1
  WScript.Echo “The value is equal to one.”
Case 2
  WScript.Echo “The value is equal to two.”
Case 3
  WScript.Echo “The value is equal to three.”
Case 4
  WScript.Echo “The value is equal to four.”
Case 5
  WScript.Echo “The value is equal to five.”
Case Else
  WScript.Echo “Value doesn’t match expected parameters.”
End Select


Uso de cadenas de texto en condiciones:


Las comparaciones entre cadenas distinguen entre mayúsculas y minúsculas. Por eso, si lo que buscamos es la presencia de una palabra o nombre lo mejor es pasarlo todo a minúsculas antes de comparar.

m = “No”
n = “NO”
If m = n Then
  WScript.Echo “Anything? Nope, I didn’t think so.”
End If
If lcase(m) = lcase(n) Then
  WScript.Echo “Values are equal when converted to lowercase.”
End If
if ucase(m) = ucase(n) Then
  WScript.Echo “Values are equal when converted to uppercase.”
End If


Bucles:

For ... Next
For i = 20 to 0 Step -1
  myArray(i) = “Unknown”
Next


For Each ... In ... Next
'Llenamos un array
Dim myArray(9)
For i = 0 to 9
  myArray(i) = “Puesto número ” & i
Next

'Lo recorremos gracias al bucle for each
For Each i IN myArray
  WScript.Echo i
Next

Exit For
For Each i IN myArray
  WScript.Echo i
  If i = “Unknown” Then
    Exit For
  EndIf
Next


Do While ... Loop
Dim y
y=0
Do While continue = True
  y = y + 1
  If y < 7 Then
    WScript.Echo “Y es menor que 7.”
  ElseIf Y = 10 Then
    WScript.Echo “Y es igual a 7.”
  Else
    WScript.Echo “Exiting the loop.”
    continue = False
  EndIf
Loop

Do ... Loop While ...
Do
  y = y + 1
  If y < 10 Then
    WScript.Echo “Y is less than 10.”
  ElseIf Y = 10 Then
    WScript.Echo “Y equals 10.”
  Else
    WScript.Echo “Exiting the loop.”
  continue = False
  EndIf
Loop While continue = True

La diferencia entre Do ... Loop While y Do While ... Loop está en el número mínimo de veces que el bucle se ejecutará. Con "Do ... Loop" el contenido del bucle se ejecuta siempre como mínimo una vez, mientras que con "Do While...Loop" puede no ejecutarse ninguna vez si la condición inicial no se cumple.

En cualquier Do... podemos salir del bucle usando: Exit Do

While ... Wend
While x < 10
  ‘Execute this code
  x = x+1
  WScript.Echo x
WEnd













Sunday, November 15, 2009

VBScript: tipos de datos

Scripting con VBScript: introducción y tipos de datos


Conviene echar un ojo a la wikipedia sobre Windows Scripting Host (WSH) para hacerse una idea del contexto en que se usa este entorno de programación. VBScript usado en el contexto del WSH permite automatizar muchas tareas típicas de la administración de sistema como p.e. las altas de usuario, los procedimientos de recuperación en caso de crash total, y típicamente para los logon script.

Para saber si Windows Scripting Host está instalado en un equipo: Inicio->Ejecutar->cmd->cscript
Si devuelve la versión es que está instalado, en caso contrario no.
Si no está instalado en un equipo 2000 o anterior se puede instalar descargándolo de la web de microsoft.
Si no está instalado en un equipo reciente, se puede ir a agregar o quitar programas, Añadir componentes de Windos, y allí añadirlo.

Este documento sólo pretende ser una referencia rápida, un resumen de las propiedades y tipos de VBScript.

Tipos de datos:



Funciones para convertir entre tipos de variable:



Arrays:
No tienen por qué contener el mismo tipo de datos. El primer elemento es el 0. Pueden tener 1 o más dimensiones.

Script de ejemplo:

a=10
b=100
c=1000
total=a*b+c
wscript.echo "El total de ",a,"*",b,"+",c,"=",total
wscript.echo "Definimos un Array de dimensión 3"

'Los arrays empiezan en la posición 0
'pueden contener tipos diferentes
Dim array(3)
'rellenamos
array(0)="posición 1"
array(1)=3
array(2)="3"
for i=0 to 2 step 1
   wscript.echo "el contenido de array(" & i & ") es de tipo: " & TypeName(array(i))
next

Sunday, November 1, 2009

Permisos sobre recursos compartidos c...

Permisos sobre recursos compartidos con Active Directory


A un recurso, como p.e. una carpeta se puede acceder básicamente de formas: en local, iniciando sesión en la máquina, ó en remoto, accediendo desde un equipo diferente al que tiene el recurso. Las carpetas a las que damos acceso por red en un equipo reciben el nombre de carpetas compartidas.


En las carpetas compartidas rigen dos tipos de permisos:
  • Sharing permissions: que se asignan desde la pestaña de compartir
  • NTFS permissions: son los permisos aplicados sobre el sistema de ficheros.



Permisos de carpeta compartida(Sharing Permissions):

Sólo hay 3 estados:
  • "Read",
  • "Change",
  • "Full Control"
Regulan el acceso por red al recurso compartido (p.e. una carpeta). El acceso está supeditado a los permisos en disco (NTFS).
P.e. si al grupo "authenticated users"le damos "Full Control" sobre una carpeta compartida, esto no le garantiza el acceso a los ficheros/carpetas de la carpeta en cuestión. Para poder acceder a ellos tendrá además que tener los correspondientes permisos de disco.






En esta tabla podeis ver claramente cómo cómo para acceder en local basta con tener permisos de disco, mientras que para acceder por red debemos tener ambos: permisos de red y permisos ntfs.


NO ntfs, No red
NO ntfs, SÍ red
SÍ ntfs, NO red
SÍ ntfs, SÍ red
abre sesión en el equipo
-
-
x
x
accede por red
-
-
-
x

Una buena opción suele ser dar acceso de lectura a todo el mundo por red, y acceso total a todos los usuarios del dominio (Domain Users), o si tenemos más de un dominio a los "Authenticated Users".

Permisos NTFS

Tipos: son mucho más complejos, en el siguiente gráfico podeis ver lo que permite hacer cada uno de ellos.




(Click aquí para ver la imagen más grande)




Controlan el acceso a los bloques de disco de un fichero o carpeta.

Los permisos se heredan por defecto de las carpetas de nivel superior.
Para añadir permisos a un nuevo grupo en una carpeta basta con ir a propiedades-> seguridad -> añadir y en la ventana que aparece seleccionar al grupo/usuario deseado. Una vez hecho esto, ajustamos el tipo de permisos que debe tener. Las carpetas que cuelgan de ésta heredarán por defecto los permisos que acabamos de asignar.
Para restringir el acceso con respecto a la carpeta de nivel superior tendremos que romper la herencia: propiedades->seguridad->Avanzadas y en la nueva ventana que aparece quitamos el check: "Allow inheritable permissions from parent to propagate ..." Nos da entonces la opción de copiar los permisos que ya había o borrarlos todos. La opción más prudente y a continuación quitar los que no proceda. Luego podemos añadir aquellos que sí deben tener acceso.




Best Practices

Normalmente los usuarios se agrupan en grupos globales siguiendo algún criterio que tenga sentido en el marco de la organización en que nos encontremos. P.e. podemos tener un grupo global por cada sede, y a la vez un grupo global por departamento. Luego añadiremos a los usuarios a los grupos globales que les corresponda.

Cuando queremos dar permisos sobre un recurso (p.e. una carpeta compartida), creamos un grupo local cuyo nombre identifique claramente el recurso al que lo querremos aplicar. Lo normal es además añadir algún identificador específico a este tipo de grupos, como p.e. que empiecen siempre por "_". Luego añadiríamos los grupos "globales" a estos grupos "locales" para dar permisos a los usuarios que contienen. Si no queda más remedio, añadiremos usuarios a los grupos locales.

Pero NUNCA añadiremos usuarios a la lista de permisos de una carpeta. Siempre añadiremos grupos, añadiremos usuarios a esos grupos, y en la correspondiente lista de seguridad añadiremos estos grupos. Es más difícil entender leyéndolo, que practicándolo.

P.e. para dar permisos sobre una carpeta "C:\grupos\contabilidad" a los usuarios de contabilidad necesitaríamos:

Grupo global: "contabilidad" en el que incluiríamos a los usuarios de contabilidad
Grupo local: "_grupos-contabilidad", al que añadiríamos al anterior grupo global "contabilidad"

Llegados a este punto, poneros un contraejemplo en el que empeceis a dar permisos a los usuarios sobre las carpetas, y pasado un tiempo intentad averiguar a qué carpetas accede un usuario concreto. ¡Ya vereis qué follón!



Monday, October 19, 2009

GPO : Group Policy Objects

GPO : Group Policy Objects

 

 

Las políticas de grupo son un método para controlar qué pueden hacer y qué no tanto usuarios como equipos. P.e. Se puede configurar el firewall del equipo, controlar el acceso del usuario al panel de control, determinar la ubicación del perfil de usuario ...

 

Hay dos tipos de Group Policies:

  • local
  • non-local

 

Las políticas locales podemos encontrarlas en cualquier equipo con Windows instalado, y podemos acceder a ellas mediante el comando gpedit.msc

 

Las non-local están en el dominio. Hablamos de ellas como GPO: Group Policies Objects (Objetos de políticas de grupo) y se almacenan en un contenedor especial del AD. Para ver ese contenedor desde la consola de AD Users and Computers (dsa.msc), hay que activar las “Advanced Features”, y lo encontraremos en: System → Policies:

 



 

Una política tiene una parte de configuración del equipo, y otra de configuración de usuario.

 

Las configuraciones de equipo se ejecutan al arrancar el equipo y con independencia del usuario que se valide en el equipo.

 

Las configuraciones de usuario se aplican con independencia del equipo en que se valide el usuario, y se aplican al iniciar sesión.

 

Los ficheros que almacenan las políticas están en la carpeta :

c:\windows\sysvol\sysvol\<nombre_dominio>\policies

 

La carpeta c:\windows\sysvol\sysvol\ es una carpeta compartida y se trata de un DFS (Distributed FileSystem) de modo que se replica entre todos los Domain Controller (DC). Por eso todos los equipos del dominio pueden acceder a las políticas y éstas son homogéneas en todo el dominio.

 

Dado que las políticas se pueden aplicar a diferentes niveles, existe un orden en la aplicación de políticas de modo que las políticas que se aplican más tarde pueden sobreescribir configuraciones establecidas por otras anteriores.

 

Orden de aplicación de políticas:

  1. local policies
  2. site policies
  3. domain policies
  4. OU policies

 

Así si p.e. si configuramos el firewall a nivel de dominio para todos los equipos del dominio, podemos modificar esa configuración para una OU en concreto creando una nueva política para esa OU que sobreescriba esa configuración de firewall.

 

Además, las configuraciones de usuario sobreescriben las configuraciones de equipo.

 

 

Estados de una política:

Una política tiene 3 estados:


No configurada

Not configured

Habilitada

Enabled

Deshabilitada

Disabled

 

No configurada

Si no está configurada significa que no realiza ningún cambio sobre ese aspecto. Es la opción por defecto.

 

Habilitada:

If you enable a policy setting, you are enabling the action of the policy setting.

For example, to revoke someone’s access to Control Panel, you enable the

policy setting Prohibit access to the Control Panel.

 

Deshabilitada:

Deshabilitar una política significa negar la acción que la describe.

 

Por ejemplo:

Por defecto un usuario puede acceder al panel de control, y por eso no es necesario deshabilitar la política: Prohibit access to the Control Panel para que pueda acceder al panel de control. Ahora bien, si previamente, en un nivel superior hemos habilitado una política que prohíbe el acceso al panel de control, y queremos habilitarlo en un nivel inferior, tendremos que deshbilitar la política.

 

 

Recomendaciones de uso

La recomendación de Microsoft es crear políticas bastante específicas, y aplicar tantas como sean necesarias antes que crear grandes políticas que configuren muchos aspectos.

Además, dado que las políticas están contenidas en ficheros, podemos ajustar los permisos sobre ellas de forma evitar su aplicación a usuarios que no toque.

 

 

Herramientas disponibles

Gpupdate:

En Windows 2000, en lugar de gpupdate, se usa secedit.

 

Su uso es:

 

 

Se trata de una utilidad de línea de comandos que permite refrescar las políticas de AD que se aplican sobre una máquina. En caso contrario, las políticas se refrescan por defecto cada 90mn.

 

Las opciones más habituales son:

 

/force: fuerza el refresco de todas las políticas, y no sólo de aquellas que han sido modificadas (comportamiento por defecto)

 

/target: permite refrescar sólo las políticas de equipo o las de usuario.

 

Gpresult:

Informa de las políticas que se aplican sobre un usuario o equipo. Su sintaxis es:



 

 

 

En palabras de microsoft:

The gpresult command displays Group Policy settings and Resultant Set of

Policy (RSoP) data for a user or a computer. You can use gpresult to see what

policy setting is in effect and to troubleshoot problems.

 

Algunos ejemplos de uso son:

C:\gpresult /user targetusername /scope computer

C:\gpresult /s srvmain /u maindom/hiropln /p p@ssW23 /user targetusername /scope USER

C:\gpresult /s srvmain /u maindom/hiropln /p p@ssW23 /user targetusername /z >policy.txt

C:\gpresult /s srvmain /u maindom/hiropln /p p@ssW23

 

GPMC:

Una nueva consola para la gestión de los GPO disponible a partir de windows 2003 R2. Está disponible para su descarga de la web de microsoft.

 



Saturday, October 3, 2009

curso - UD I virtualbox

Unidad didáctica I: VIRTUALBOX


Presentación
Esta primera unidad didáctica es principalmente práctica.

Pasos generales a seguir para preparar una nueva máquina virtual:
  1. Clonar el disco de sistema que toque (p.e. el de windows xp)
  2. Registrar el disco en el gestor de medios
  3. Crear la máquina virtual y asignarle el disco recién creado.
  4. Arrancar la máquina virtual sin conectar el cable de red, y cambiar el SID y el nombre, y si procede la ip, ...
  5. Instalar las Guest Addition

Prueba en Windows: añadir la carpeta de instalación del virtualbox a la variable path para ver si así no hay que ejecutar Virtualbox desde la carpeta de instalación.

Usuarios ubuntu: realizar la instalación añadiendo el repositorio de Virtualbox al sources.list del apt, y añadir también el certificado del repositorio.

Clonar disco:
Hay dos métodos, el primero es el oficial:
a) VBoxManage clonehd "DiskToClone.vdi" "ClonedDisk.vdi"
El segundo no es oficial, pero parece que funciona:
b)se copia el fichero y después:
VBoxManage internalcommands setvdiuuid "CopiedDisk.vdi"

Conocimientos a adquirir por vuestra cuenta:
  • Compartir una carpeta entre anfitrión y guest
  • Instalar las VBoxGuestAdditions
  • conectar/desconectar un cd o imagen ISO a una máquina

Errores comunes:
  • Poner mal la ruta del disco que queremos clonar (si hay espacios en blanco hay que poner comillas)
  • el disco que queremos clonar ya lo hemos añadido en el gestor de dispositivos virtuales ...
  • no ejecutar el VBoxManage desde la carpeta de instalación del VirtualBox
  • no respetar mayúsculas/minúsculas en las opciones del VBoxManage (p.e. Clonehd fallaría, es clonehd)


Ejercicios propuestos para el entorno Windows:
Modificar alguna de las variables de sistema para ver si así se puede ejecutar el VBoxManage con independencia de la ruta en que esteis.

Ejercicios propuestos para cualquier entorno:
Registrar un disco en el "Virtual media manager" y luego intentar clonarlo. Dará un error. Fijaros cual es y que habla del uuid del disco. Luego intentar deshacer el entuerto y finalmente conseguir clonar el disco.

Friday, August 14, 2009

Python: parsear un fichero y cambiar el contenido de una línea

Este script crea parsea el fichero de configuración del apache2 en la ruta que le indiquemos y substituye el DocumentRoot del VirtualHost que le indiquemos por uno nuevo que también le pasamos por parámetro:

./scriptillo.py <ruta_al_fichero_de_configuración> <VirtualHost> <nueva_ruta>

El contenido del fichero es:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from cStringIO import StringIO
import re

# r'<VirtualHost\s(.*?)>' significa cadena de tipo raw
# que coincide con <VirtualHost más cualquier cadena de espacios
# tabuladores ... lo que sea más cualquier carácter que no sea fin de línea
# o ninguno, y acabe en >
vhost_start = re.compile(r'<VirtualHost\s(.*?)>')
vhost_end = re.compile(r'</VirtualHost')
# r'(DocumentRoot\s+)(\S+)' significa cadena de tipo raw
# (DocumentRoot\s+) significa que cumple que tiene DocumentRoot más una
# o más espacios o similar; y además lo anterior va seguido de una cadena
# diferente de espacios en blanco.
docroot_re = re.compile(r'(DocumentRoot\s+)(\S+)')

def replace_docroot(conf_string, vhost, new_docroot):
'''yield new lines of an httpd.conf file where docroot lines matching
the specified vhost are replaced with the new_docroot
'''
conf_file = StringIO(conf_string)
# variable que controla si estamos en el VirtualHost correcto
in_vhost = False
# Inicializamos curr_vhost como objeto
curr_vhost = None
for line in conf_file :
# comprobamos si la línea es del tipo <VirtualHost ...>
vhost_start_match = vhost_start.search(line)
# Si lo es, asignamos curr_vhost el nombre al que
# responde el VirtualHost:<puerto> que estamos leyendo
if vhost_start_match :
curr_vhost = vhost_start_match.groups()[0]
in_vhost = True
# Si estamos en un VirtualHost y es el que le hemos indicado
# empezamos a buscar la línea de DocumentRoot y hacemos la substitución
if in_vhost and (curr_vhost == vhost) :
doc_root_match = docroot_re.search(line)
if doc_root_match :
sub_line = docroot_re.sub(r'\1%s' % new_docroot, line)
line = sub_line
# Comprobamos si hemos llegado al final del VirtualHost
# y si es así reseteamos la variable in_vhost
vhost_end_match = vhost_end.search(line)
if vhost_end_match :
in_vhost = False
yield line

if __name__=='__main__' :
import sys
# fichero de configuración de apache2
conf_file = sys.argv[1]
# VirtualHost cuyo DocumentRoot hay que modificar
vhost = sys.argv[2]
# nuevo DocumentRoot
docroot = sys.argv[3]

# leemos del fichero de configuración
conf_string = open(conf_file).read()
# para cada línea llamamos a la función encargada de hacer la
# substitución si es necesario
for line in replace_docroot(conf_string,vhost,docroot):
print line

Thursday, August 13, 2009

Python: expresiones regulares (2)

Se trata de ampliar un poco lo de las expresiones regulares con un par de ejemplos:

import re
vhost_start = re.compile(r'<VirtualHost\s(.*?)>')
  • r al principio signifa que es una raw string por eso no escapo el <
  • <VirtualHost\s significa que buscamos <VirtualHost seguido de cualquier carácter de espacio en blanco (\t\n\r\f\v)
  • (.*?) el . significa cualquier carácter menos newline, * significa n veces la condición anterior, ? precedido de * significa al menos 1 vez la condición anterior
  • > que acabe en >

docroot_re = re.compile(r'(DocumentRoot\s+)(\S+)')

  • r'...' significa cadena de tipo raw
  • (DocumentRoot\s+) significa que cumple que tiene DocumentRoot más uno o más espacios o similar
  • (\S+) lo anterior va seguido de una cadena diferente de espacios en blanco.

Python: expresiones regulares

Para trabajar con expresiones regulares en python hay que importar el módulo re, que contiene:

import re

help(re)
....
This module exports the following functions:
match Match a regular expression pattern to the beginning of a string.
search Search a string for the presence of a pattern.
sub Substitute occurrences of a pattern found in a string.
subn Same as sub, but also return the number of substitutions made.
split Split a string by the occurrences of a pattern.
findall Find all occurrences of a pattern in a string.
finditer Return an iterator yielding a match object for each match.
compile Compile a pattern into a RegexObject.
purge Clear the regular expression cache.
escape Backslash all non-alphanumerics in a string.
....


Las búsquedas se pueden hacer compilando previamente el patrón o sin compilarlo.

Sin compilar:
#!/usr/bin/env python
import re

patron=";;(.*?);;"
texto="aquí el nombre ;;campo1;; y aquí los apellidos ;;campo2;;"

for campo in re.findall(patron,texto):
print "Coincidencia : ",campo


Compilando: (creando el objeto expresión regular)
#!/usr/bin/env python
import re

patron=re.compile(";;(.*?);;")
texto="aquí el nombre ;;campo1;; y aquí los apellidos ;;campo2;;"

for campo in patron.findall(texto):
print "Coincidencia : ",campo


La diferencia está en que con el segundo proceder creamos un objeto "expresión regular" que contendrá los métodos propios de una expresión regular. P.e. findall, search ... La segunda diferencia es que al llamar al método findall en el primer caso accedemos al módulo y en el segundo al método del objeto.

Sobre una única ejecución en un fichero medio no va mucha diferencia, aunque la hay. A continuación pongo un ejemplo en que sí la hay al abrir un fichero de log de 80000 líneas y hacer una búsqueda repetidamente.

Compilando: (creando el objeto expresión regular)



#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

def run_re():
pattern = "ass"
re_obj = re.compile(pattern)
infile = open ("/var/log/dpkg.log.1","r")

match_count = 0
lines = 0

for line in infile:
match = re_obj.search(line)
if match :
match_count += 1
lines += 1
return (lines , match_count)

if __name__=="__main__" :
lines,match_count = run_re()
print "Lines :: ",lines
print "Matches :: ",match_count


Sin crear el objeto expresión regular:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

def run_re():
pattern = "ass"
infile = open ("/var/log/dpkg.log.1","r")

match_count = 0
lines = 0

for line in infile:
match = re.search(pattern,line)
if match :
match_count += 1
lines += 1

return (lines,match_count)

if __name__=='__main__' :
lines,match_count = run_re()
print "Lines :: ",lines
print "Matches :: ",match_count

Saturday, March 7, 2009

Primicia


Hoy adelanto la tira cómica que publicarà el caballero oscuro en lasombradelmurcielago.blogspot.com

Un honor y un placer.