Archivo de la etiqueta: SharePoint

“Configurar grupos para este sitio” en SharePoint 2010

sharepoint2010Una de las cosas que echo de menos de SharePoint 2007 en SharePoint 2010 es la pagina de “Configurar grupos para este sitio” o en inglés “Set up Groups for this site“, donde el usuario puede especificar quién puede tener acceso a un  sitio en concreto. Esta claro que he mejorado mucho la forma de gestionar los grupos y usuarios, pero hecho en falta esta pagina (y sobre todo su funcionalidad)…

 

ConfigurarGrupos

Por algún motivo, el equipo de SharePoint decidió que esta funcionalidad “Configurar grupos de este sitio” debía de estar oculta en el menú de Permisos del Sitio. Si que esta visible, cuando creas un Sitio nuevo (si lo creas con la opción de permisos únicos), la malo es que luego, no hay forma de ver los grupos asignados a cada perfil.

Si necesitas realizar cambios en la asignación de grupos y como esta funcionalidad sigue estando en SharePoint 2010, siempre es posible acceder a la pagina por url: /_layouts/permsetup.aspx

 

ViewFormPagesLockdown para aumentar la seguridad en SharePoint 2010

sharepoint2010 Ayudando a un amigo, vimos que en portales públicos en los que se utiliza SharePoint 2010, puedes tener una mala configuración que a nivel de seguridad, puede ser problemático.

Cuando creas un portal publico (usando las características de Publicación) basado en SharePoint, has de configurar el acceso de usuarios, como anónimo, por lo que por defecto permite que cualquier usuario acceda a los siguientes recursos:

  • /_layouts/viewlsts.aspx
  • /Lists/[ListName]/AlItems.aspx

Esto es un problema de seguridad, ya que estas dando una información muy importante a usuarios anónimos, que podrían usar en tu contra… pero no hay problema ya que SharePoint trae una característica oculta a nivel de Site, llamada ViewFormPagesLockdown, que deshabilita el acceso a estos recursos de forma anónima.

Para activar esta funcionalidad, hay que utilizar un par de comandos de PowerShell:

1) Obtenemos el GUID de la característica ViewFormPagesLockdown, la cual como he comentado esta oculta con el siguiente comando:

Get-SPFeature | where { $_.DisplayName -eq "ViewFormPagesLockdown"}

ViewFormPagesLockdown

2) Una vez tenemos el GUID o identificador, lo que hacemos es activarlo:

Enable-SPFeature -url http://sharepoint -identity 7c637b23-06c4-4724-9a9a-7c175762c5c4 -confirm:$false

Tras este cambio, los usuarios tendrán que autenticarse, para acceder a estos recursos.

IMPORTANTE: Puedes tener problemas si dentro de esta colección de sitio, tienes subsitios de tipo Blog, en los que los usuarios pueden realizar comentarios sobre post o similares… para solucionar este tipo de problema, en el blog de sharepointblues.com te explican como se puede solucionar.

Como lanzar un Workflow programaticamente en SharePoint

Tras un periodo de inactividad, vuelvo con un nuevo post… Esta vez se trata, de la necesidad de lanzar un nuevo Workflow a nivel de listas o biblioteca en todos los ítems, previamente creados. Si el Workflow se configura para que se lance a la creación o modificación del ítem, puede que haya muchos ítems, que por antigüedad, no se modifiquen y no se lance el Workflow asociado.

Para realizar esto desde el API de SharePoint, la forma mas sencilla es la siguiente:

static private void LanzarWorkflow()
{
  //definición de variables necesarias para la ejecución
  string SP_URL = "http://mi_sharepoint";
  string LIST_NAME = "Pages";
  //este es el GUID del BaseID del Workflow que queremos ejecutar
  Guid wfBaseId = new Guid("b81abdd8-faf4-4bed-86ca-a49d9cc9913e");
  //se ejecuta con privilegios elevados
  SPSecurity.RunWithElevatedPrivileges(delegate
  {
	try
	{
	  using (SPSite site = new SPSite(SP_URL))
	  {
		using (SPWeb web = site.OpenWeb())
		{
		  SPList list = web.Lists[LIST_NAME];
		  SPListItemCollection items = list.Items;
		  for (int i = 0; i < items.Count; i++)
		  {
			web.AllowUnsafeUpdates = true;  
			//selecciona el item actual
			SPListItem item = items[i];
			Console.WriteLine(string.Format("[Item] Lanzando workflow para el item Id: {0} ", item.ID));
			//obtiene el objeto plantilla de WF asociado a la lista que queremos
			SPWorkflowAssociation associationTemplate = list.WorkflowAssociations.GetAssociationByBaseID(wfBaseId);
			//lanzar el WF a nivel del item
			web.Site.WorkflowManager.StartWorkflow(item, associationTemplate, associationTemplate.AssociationData);
			web.AllowUnsafeUpdates = false; //bloquea cambios por codigo
		  }
		}
	  }
	}
	catch (Exception ex) { Console.WriteLine(string.Format("***ERROR*** {0}", ex.ToString())); }
  });
}

Los únicos parámetros que necesita esta función son:

  • SP_URL: Url del sitio de SharePoint donde se encuentra la lista que tiene asociada el Workflow que deseamos lanzar
  • LIST_NAME: Nombre de la lista o biblioteca que tiene el Workflow
  • wfBaseId: por ultimo el Base ID del Workflow (este GUID lo puedes ver, por ejemplo, desde SharePoint Designer, editando el archivo XML de configuración del propio Workflow)

 

Listado de permisos de usuarios de un sitio en SharePoint 2010

powershellUna de las ultimas cosas que me han solicitado es recuperar todos los usuarios y sus permisos de una colección de sitio o subsitio en SharePoint 2010

La forma mas rápida que se me ocurrió es la de crear un script de PowerShell para ello. Como creo que os podría ser de utilidad, lo comparto con todos vosotros:

function Get-UsersPermissions([string]$portalurl, [String[]]$excludewebs, [string]$onesite) 
{ 
    [void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") 
    $farm = [Microsoft.SharePoint.Administration.SPFarm]::Local 
	#añade la barra si no existe
    if (-not $portalurl.EndsWith("/")) { $portalurl = $portalurl + "/" } 
	#recorre todos los servicios de la granaja
    foreach ($spService in $farm.Services) 
	{ 
        if (!($spService -is [Microsoft.SharePoint.Administration.SPWebService])) { continue; } 
        foreach ($webApp in $spService.WebApplications) 
		{ 
            if ($webApp -is [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]) { continue; } 
			$webAppUrl = $webApp.GetResponseUri('Default').AbsoluteUri 
			if ($webAppUrl.ToUpper() -eq $portalurl.ToUpper())
			{ 
				#recorre las colecciones que existen en la aplicacion web
				foreach ($site in $webApp.Sites) 
				{ 
					#si existe algun parametro 
					if (($onesite -ne $null) -and ($onesite -ne "")) 
					{ 
						#verifica si se ha incluido el parametro Web
						if ($site.Url.ToUpper() -ne $onesite.ToUpper()) { continue; } 
					} 
					#recorre los sitios que existen en la coleccion
					foreach ($web in $site.AllWebs) 
					{ 
						if ($excludewebs -contains $web.Url) 
						{ 
							Write-Host "Se ha excluido el sigioente sitio: " $web.Url 
							continue 
						} 
						foreach ($user in $web.SiteUsers)
						{ 
							#excluye al usuario: sharepoint\system 
							if ($user.Loginname.StartsWith("SHAREPOINT\")) { continue; } 
							#recupera la informacion a mostrar
							$data = @{ 
										"Coleccion" = $site.Url 
										"Url sitio" = $web.Url 
										"Nombre sitio" = $web.Title 
										"Usuario" = $user.Loginname 
										"Nombre" = $user.Name 
										"Roles" = $user.Roles 
										"Grupos" = $user.Groups 
							} 
							New-Object PSObject -Property $data 
						} 
						$web.Dispose(); 
					} 
					$site.Dispose() 
				} 
			} 
		} 
	} 
}

#---------------------------------------------------------------
#Opcion 1: Listas de los usuarios y sitio del la Aplicacion Web: http://intranet, pero solo muestra los usuarios y permisos del subsitio: http://intranet/sites/test
# Get-UsersPermissions -portalurl:http://intranet/  -onesite:http://intranet/sites/test | Out-GridView
#---------------------------------------------------------------
#Opcion 2: Listas de los usuarios y sitio del la Aplicacion Web http://intranet, pero excluye los 3 sitios: /gastos, /docs y /rrhh
# Get-UsersPermissions -portalurl:http://intranet/ -excludewebs:@('http://intranet/gastos','http://intranet/docs','http://intranet/rrhh')  | Out-GridView
#---------------------------------------------------------------
#Opcion 3: Lista todas los sitios y usuarios de la Aplicacion Web: http://intranet
# Get-UsersPermissions -portalurl:http://intranet/ | Out-GridView
#---------------------------------------------------------------

Editar plantillas de SharePoint (archivos stp) de una forma cómoda y sencilla

sharepoint2010Es posible que te hayas visto en la necesidad de tener que editar plantillas de listas de SharePoint, para pasarlas a una granja diferente o similar… Una cosa que suele ser común es que en tu servidor de pruebas no tengas todos los Language Packs instalados, y cuando quieras usar dichas plantillas de lista, no puedas hacerlo.

Para poder realizar esto, es necesitar editar el manifiesto de la planilla y ponerle el idioma, que tengas instalado en tu entorno. Para editar un archivo stp existen varios métodos que comento a continuación:

1) Existe una forma manual de poder editarlos, cuyos pasos serian:

  1. Copia y renombra la extensión del archivo .stp por .cab
  2. Extrae el contenido del archivo (yo suelo usar WinRar)
  3. Abre el archivo manifest.xml en un editor de texto (Visual Studio, Notepad, Dreamweaver, etc.)
  4. Modifica el archivo manifest.xml
  5. Usando la linea de comando,  sitúate en el directorio/carpeta que contenga el manifiesto ya editado
  6. Teclea el siguiente comando, sustituyendo el <nombre_plantilla> por el deseado: makecab.exe manifest.xml <nombre_plantilla>.cab
  7. Esto generará un archivo .cab que deberemos renombrar de extensión a .stp
  8. Ya tenemos listo la plantilla modificada, preparada para subir a SharePoint

makecab01

2) Existe otra forma mucho mas sencilla, cuyos pasos serian:

  1. Copia y renombra la extensión del archivo .stp por .cab
  2. Extrae el contenido del archivo (yo suelo usar WinRar)
  3. Abre el archivo manifest.xml en un editor de texto (Visual Studio, Notepad, Dreamweaver, etc.)
  4. Modifica el archivo manifest.xml
  5. Buscar la aplicación iexpress.exe y ejecutala
  6. Sigue los pasos del wizard
  7. Esto generará un archivo .cab que deberemos renombrar de extensión a .stp
  8. Ya tenemos listo la plantilla modificada, preparada para subir a SharePoint

IEXPRESS02

Este segundo paso es mucho mas cómodo si tu plantilla, contiene mas de un archivo (es decir a aparte del manifest.xml) ya que no tienes que generar ningún script para que te haga el empaquetado usando makecab.

Para más información sobre IExpress Wizard, puedes consultar esta pagina de Microsoft.

 

DisableLoopbackCheck en SharePoint 2010

Uno de los problemas con el que nos podemos encontrar los desarrolladores de SharePoint 2010, es que cada vez que intentamos acceder a sitios de nuestros entornos de desarrollo o preproducción de SharePoint, que se habíamos creado previamente, nos pide en repetidas ocasiones (las tres de rigor) su usuario y contraseña antes de devolver un error 401.1 Access Denied y una entrada en el Visor de Eventos de Windows.

En principio esto no debe de ser un problema ya que ningún usuario usa directamente los servidores de la granja de SharePoint para navegar por los sitios ahí hosteados. Pero ¿y si es un servidor de desarrollo o pruebas? En estos casos es obligatorio que podamos acceder a los sitios sin que este comportamiento ocurra.

Este comportamiento del sistema, es una característica de seguridad introducida desde el Service Pack 1 de Windows Server 2003 y está presente hasta las versiones actuales de Windows Server 2008 R2. Básicamente lo que hace es bloquear el acceso a una Web Application usando el FQDN, si esto sucede la característica entra en acción y bloquea este acceso enviando un error 401.1 Access Denied. ¿Por qué se introdujo esta característica? Pues porque existían varios ataques que se basaban en reflección para engañar a IE y hacerle creer que se estaba trabajando de manera local y así burlar muchas restricciones de seguridad.

¿Como podemos solucionar este problema (siempre y cuando se traten de entornos no productivos)? Existen dos métodos .. uno a través de la ejecución de un comando de PowerShell y la segunda añadiendo una clave en el Registro de Windows.

1) Ejecución de este comando PowerShell:

New-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa -Name "DisableLoopbackCheck" -value "1" -PropertyType dword

En la siguiente imagen puede apreciarse la ejecución de este comando:

2) Modificando directamente el Registro de Windows:

– Pincha en el botón de Inicio o presiona la tecla Windows + X (dependiendo la versión de Windows), pincha en Ejecutar, escribe: “regedit” y presiona Intro.
– En el editor del Registro de Windows, localiza la siguiente clave: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
– Pincha con el botón derecho del ratón en Lsa, selecciona nueva Valor de DWORD (32 bits)


– Introducimos el nombre “DisableLoopbackCheck” y presionamos Intro.
– Pinchamos con el botón derecho del raton sobre esta nueva clave “DisableLoopbackCheck“, y seleccionamos Modificar.
– Introducimos un “1” en el campo Información del valor  y presionamos Intro.


– Cerramos el editor del Registro de Windows y reiniciamos el servidor para que los cambios tengan efecto.

Para información mas detallada sobre este problema, podéis consultar el KB896861.

 

Eliminar características de la base de datos de contenido con PowerShell

Una de mis tareas es revisar el Analizador de mantenimiento de SharePoint 2010, donde quedan registrados problemas que pueden hacer que una granja de SharePoint tenga problemas de seguridad, escalabilidad, rendimiento…

Uno de los problemas que he detectado y que viene siendo recurrente, es soluciones han sido eliminadas, antes de que las características correspondientes hayan sido desactivadas de colecciones de sitios y sitios.

Este problema queda registrado en el  Analizador de mantenimiento, con la categoría a nivel de granja: “Missing server side dependencies“.

Dentro de esta categoría, puedes encontrar registros como el siguiente, donde se detallo el problema:

[MissingFeature] Database [_WSS_DSI01] has reference(s) to a missing feature: Id = [e8389ec7-70fd-4179-a1c4-6fcb4342d7a0]. The feature with Id e8389ec7-70fd-4179-a1c4-6fcb4342d7a0 is referenced in the database [_WSS_DSI01], but is not installed on the current farm. The missing feature may cause upgrade to fail. Please install any solution which contains the feature and restart upgrade if necessary.

Este mensaje de error indica un nombre de base de datos de contenido (_WSS_DSI01) y el identificador de la característica (e8389ec7-70fd-4179-a1c4-6fcb4342d7a0), lo malo es que este error, no informa sobre los sitios o colecciones de sitios donde la característica existe y además, aunque supiéramos donde se ha activado esta característica, no es posible desde el interfaz de usuario desactivarla, ya que dicha solución se ha eliminado de la granja.

El siguiente script de PowerShell, nos informa de que sitios o colecciones de sitio de la base de datos de contenido, contienen la referencia a esta característica y fuerza la desactivación de de esta.

function Remove-SPFeatureFromContentDB($ContentDb, $FeatureId, [switch]$ReportOnly)
{
    $db = Get-SPDatabase | where { $_.Name -eq $ContentDb }
    [bool]$report = $false
    if ($ReportOnly) { $report = $true }
    $db.Sites | ForEach-Object 
    {
        Remove-SPFeature -obj $_ -objName "site collection" -featId $FeatureId -report $report
        $_ | Get-SPWeb -Limit all | ForEach-Object 
        {
            Remove-SPFeature -obj $_ -objName "site" -featId $FeatureId -report $report
        }
    }
}

function Remove-SPFeature($obj, $objName, $featId, [bool]$report)
{
    $feature = $obj.Features[$featId]
    if ($feature -ne $null) 
    {
        if ($report) 
        {
            write-host "Feature found in" $objName ":" $obj.Url -foregroundcolor Red
        }
        else
        {
            try 
            {
                $obj.Features.Remove($feature.DefinitionId, $true)
                write-host "Feature successfully removed from" $objName ":" $obj.Url -foregroundcolor Red
            }
            catch 
            {
                write-host "There has been an error trying to remove the feature:" $_
            }
        }
    }
    else 
    {
        #write-host "Feature ID specified does not exist in" $objName ":" $obj.Url
    }
}

 

Si únicamente queremos obtener el listado de sitios y colecciones de sitios, donde se referencia esta característica, deberás utilizando de la siguiente forma:

Remove-SPFeatureFromContentDB -ContentDB "_WSS_DSI01" -FeatureId "e8389ec7-70fd-4179-a1c4-6fcb4342d7a0" –ReportOnly

 

Si por el contrario, además de obtener el listado, deseas eliminar las referencias de la base de dato de contenido, deberás utilizarlo como anteriormente, el único cambio es que has de eliminar el parámetro “–ReportOnly”:

Remove-SPFeatureFromContentDB -ContentDB "_WSS_DSI01" -FeatureId "e8389ec7-70fd-4179-a1c4-6fcb4342d7a0"

 

Una vez hayas eliminado todas las referencias erróneas, es necesario volver a analizar  la categoría: “Missing server side dependencies” dentro del Analizador de mantenimiento, para comprobar que los errores han desaparecido.

Referencia: get-spscripts.com

 

Consultar los logs de ULS de SharePoint 2010 en SQL Server

Es posible que se os haya dado el caso de tener que consultar los logs de SharePoint 2010 conocidos como Unified Logging System (ULS), en entornos formados por grandes granjas de servidores… Este proceso en este caso se convierte en algo tedioso, si no tienes forma de identificar en que servidor físico estas haciendo la petición, para consultar su Correlation ID.

Antes de nada indicar que Microsoft recomienda no acceder directamente a la información de la plataforma, desde la base de datos, sino que debe hacerse a través del modelo de objetos de SharePoint. Este seria el único caso excepcional, donde podemos acceder directamente a través de consultas SQL.

SharePoint 2010, a nivel de granja crea una base de datos llamada WSS_Logging, donde almacena toda la información de la plataforma SharePoint, como por ejemplo: información que envía al visor de eventos de Windows, información de los contadores de rendimiento, inventario de los sitios existentes, los logs de ULS… eso si con un periodo de antigüedad de 14 días, toda información que pase de ese tiempo sera eliminada.

La información de esta base de datos, también es usada para consolidar los datos de Web Analytics a través de los jobs Microsoft SharePoint Foundation Usage Data Import y Microsoft SharePoint Foundation Usage Data Processing.

También es importante remarcar, que la información se vuelca desde la granja a la tabla WSS_Logging, a través de varios timer job que se ejecuta cada varios minutos (este valor es diferente para cada uno de ellos). Aquí tenéis el listado de jobs que vuelca información a esta base de datos (estos datos pueden consultarse en la Administración Central):

El job en concreto, que actualiza la información en el ULS es: Diagnostic Data Provider: Trace Log y se ejecuta por defecto cada 10 minutos y esta es su configuración:

Si, como comentábamos anteriormente, queremos acceder a la misma información que existe en los logs de SharePoint, directamente, deberemos realizar consultas sobre la vista: [dbo].[ULSTraceLog]. Es importante remarcar que debes utilizar las vistas y no las tablas para realizar las consultas.

Los campos de esta vista son: [PartitionId], [RowId], [LogTime], [MachineName], [ProcessID], [ProcessName], [ThreadID], [Area], [Category], [Level], [EventID], [Message], [CorrelationId], [RowCreatedTime]. Estos campos son similares a la informacion que se almacenan en los archivos de ULS.

Como veis existe el campo  [CorrelationId] por el cual vamos a conseguir filtrar los datos, para cotar la información.

De este modo, podrás localizar registros de logs sin tener que buscar físicamente en varios archivos ULS, a través de la granja…

Crear items con servicios REST de diferentes tipos de contenido

Otra duda que se nos ha planteado es la creación de items en una lista o biblioteca de diferentes tipos de contenido utilizando servicios REST en  SharePoint 2010.

Previamente ya habíamos visto como Listar, añadir, modificar y borrar información con REST en SharePoint 2010, pero partíamos que la lista o biblioteca solo tenia un tipo de contenido por defecto. Ahora se nos plantea un complicación mas, que es crear un ítem de un tipo de contenido concreto.

Suponemos que tenemos la lista “DemoList” a la cual tiene el tipo de contenido por defecto “Elemento” y le hemos añadido un segundo tipo de contenido llamado “Anuncio”.

Ahora queremos añadir un nuevo item de tipo “Anuncio”… lo que deberíamos hacer es definir ese nuevo item y especificar su tipo de contenido:

static void CreateDataContentType()
{
	//recupera la informacion del servicio 
	DevPortalHomeDataContext dataContext = new DevPortalHomeDataContext(new Uri("http://servidor/_vti_bin/listdata.svc/"));
	dataContext.Credentials = CredentialCache.DefaultNetworkCredentials; 
	//crea y define un nuevo item en la lista DemoList (definimos el Content Type)
	DemoListItem demoListItem = new DemoListItem()
	{
		ContentType = "Announcement",
		Title = "Registro de tipo contenido Anuncio",
		Cuerpo = "Cuerpo del anuncio"
	};
	//añade el item a la lista
	dataContext.AddToDemoList(demoListItem);
	dataContext.SaveChanges();
	Console.WriteLine("Registro creado correctamente");
}

En el caso de no especificar el campo ContentType, SharePoint asume que el nuevo item, es del tipo de contenido predeterminado.

En la siguiente imagen se puede apreciar, como el nuevo registro añadido con esta función, es de tipo “Anuncio”:

 Es importante saber que has de conocer los posibles tipos de contenido de la lista en cuestión, ya que no hay forma de saber (ni siquiera con los metadatos: http://servidor/_vti_bin/listdata.svc/$metadata) de los posibles valores del campo: <Property Name=”TipoDeContenido” Type=”Edm.String” Nullable=”true” />.