Ativação do host baseando-se na memória

by Israel Aece 20. October 2009 09:03

O WCF fornece uma opção que nos permite configurar a porcentagem mínima de memória disponível na máquina antes de ativar o serviço. Para customizar isso, recorremos a propriedade (atributo) MinFreeMemoryPercentageToActivateService da classe (elemento) ServiceHostingEnvironmentSection. Essa propriedade recebe um número inteiro, que corresponde a quantidade de memória disponível que a máquina onde o serviço está rodando deverá ter disponível.

Como essa configuração recorre a métodos não gerenciados para fazer essa verificação, a aplicação (serviço) deverá estar rodando em full-trust. Caso contrário, uma exceção do tipo SecurityException será disparada e, consequentemente, o serviço não estará disponível para receber requisições.

Tags: , ,

WCF

Utilizando o EF em Ambiente Parcialmente Confiável

by Israel Aece 16. July 2009 08:51

Estava utilizando a template de projeto Web Site para a criação de um site com uma vida curta, e que se destina a realizar uma tarefa temporária. Como ele deve acessar uma fonte de dados SQL Server para manipular alguns dados, optei por utilizar o Entity Framework como forma de acesso, ao invés do LINQ To SQL ou até mesmo do ADO.NET.

Em pouco tempo essa aplicação ficou pronta e tudo funcionava tranquilamente na máquina de desenvolvimento, até que decidi - erroneamente - configurar o Web.Config localmente. Entre essas configurações, uma delas foi ajustar o nível de segurança que a aplicação deverá rodar, que – teoricamente – não preciso nada mais do que o nível "Medium". Sendo assim, o meu arquivo Web.Config passou a ficar com a seguinte entrada:

<trust level="Medium" />

Ao tentar recompilar a aplicação no Visual Studio .NET, me deparo com o seguinte erro listado na IDE:

Type ‘System.Data.Entity.EntityDesignerBuildProvider’ cannot be instantiated under a partially trusted security policy (AllowPartiallyTrustedCallersAttribute is not present on the target assembly).

Ao abrir o arquivo Web.Config da aplicação, você notará que no elemento connectionStrings possuirá as referências para os arquivos que possuem as descrições das entidades e mapeamentos (CSDL, MSL e SSDL), acrescentado o prefixo "res://", que indica que eles serão adicionados ao assembly como Resource.

Além disso, você verá que existe um builder provider do tipo EntityDesignerBuildProvider, vinculado à aplicação. Essa classe é responsável por extrair as informações dos arquivos mencionados acima, e modificar os assemblies que estão sendo gerados, embutindo-as como Resources. Esse processo não pode ser executado em ambiente parcialmente confiável, já que a permissão necessária não será concedida à aplicação. Veja que a mensagem de erro informa que o Assembly onde está declarado este builder provider, não pode ser chamado por aplicações parcialmente confiáveis, pois a ausência do atributo AllowPartiallyTrustedCallersAttribute evita isso.

A transformação do arquivo EDMX (CSDL, MSL e SSDL) ocorre somente na primeira vez que se compila a aplicação (%windir%\Microsoft.NET\Framework\Versao\Temporary ASP.NET Files), e se nesse momento estiver com ela configurada como parcialmente confiável, assim como eu fiz acima, você irá obter o erro em questão. Se você optar por pré-compilar a aplicação em ambiente “FullTrust”, e fazer o deployment em ambiente parcialmente confiável, você não terá este problema. Isso é perfeitamente possível, já que as configurações de uma aplicação (Web.Config) não são compiladas.

Uma outra alternativa é utilizar o conceito de sandboxing, onde você isola o EDMX em uma Class Library, e faz referencia para ela no projeto Web. Como o arquivo EDMX estará embutido na DLL gerada, você não precisa mais das referências aos arquivos CSDL, MSL e SSDL na aplicação Web, e muito menos do build provider EntityDesignerBuildProvider no Web.Config. Neste caso, o ponto negativo é ter que gerenciar dois projetos e Assemblies.

Ainda há uma última alternativa neste caso, onde você extrai os arquivos CSDL, MSL e SSDL a partir do EDMX, e modifica a connectionString para apontar fisicamente para estes arquivos, que devem estar na mesma aplicação (talvez no diretório bin). Particularmente prefiro a opção da geração do Assembly a parte, que facilita a reutilização por várias aplicações e não corremos o risco de alguém, acidentalmente, excluir estes arquivos que são necessários para o Entity Framework trabalhar.

Tags: ,

ASP.NET | Data | Security

Security-Transparent Code

by Israel Aece 14. July 2009 19:06

Uma das grandes inovações que o .NET trouxe é a capacidade de conceder ou negar acesso à uma determinada aplicação (Assembly), independentemente do usuário que está acessando-a, sendo ou não um “Administrador” da máquina onde a aplicação está sendo executada. Esse novo conceito, presente desde a primeira versão do .NET Framework, é chamada de Code Access Security – CAS.

Esse recurso é extremamente rico em detalhes, onde podemos customizar quais direitos a aplicação terá baseando-se em condições que são avaliadas durante a execução da mesma.  Para compor o CAS, temos vários objetos, tais como: Permissions, Permissions Sets, Security Levels, Membership Conditions, Demands, etc. Ao mesmo tempo que isso é extremamente poderoso, a sua configuração torna-se complexa demais, principalmente quando você não tem um conhecimento intermediário sobre o seu funcionamento.

Um dos principais cenários onde precisamos fazer o uso destas funcionalidades, é quando estamos criando libraries (DLLs) para serem consumidas em ambientes parcialmente confiáveis, ou seja, você cria uma DLL para encapsular o acesso ao banco de dados, sistema de arquivos, etc., e quer consumí-la em uma aplicação que não está sendo executada em “FullTrust” (o que muitas vezes acontece). Nesses casos, se gasta mais tempo testando e configurando as políticas com seus respectivos níveis de segurança, do que na tarefa que a DLL irá executar.

A partir do .NET Framework 2.0, a Microsoft trouxe um recurso chamado de Security-Transparent Code. Essa funcionalidade facilita a escrita e configuração de DLLs que serão consumidas por aplicações que rodam em ambientes parcialmente confiáveis. A ideia desta técnica é você refatorar o código (seja em assemblies, classes ou métodos) em “código transparente” e “código crítico”, com o propósito de separar o código que roda como parte da aplicação do código que roda como parte da infraestrutura, criando uma espécie de barreira entre essas duas seções.

O “código transparente” não fará nada (do ponto de vista da segurança) além do que lhe foi concedido, ou seja, não acessará nenhum tipo de código que exija a elevação dos privilégios atuais. Ao precisar executar uma tarefa que exige um nível de segurança mais elevado, entre em cena o “código crítico”, que rodará em “FullTrust”. Neste caso, o “código transparente” irá invocar algum membro do “código crítico”, que possuirá todos os privilégios necessários, independentemente de quais o cliente possua, evitando elevar os privilégios do “código transparente”.

Os códigos marcados como “transparente” terão algumas restrições, tais como: elevar os privilégios (Asserts) que lhe foram concedidos; efetuar Link Demands (tudo será transformado em “full demand”) e qualquer código unsafe que ele eventualmente execute em “código transparente”, também efetuará uma “full demand”.

Observação: A diferença entre Link Demand e Demand (ou Full Demand) é que a primeira ocorre somente em tempo de compilação (JIT) e apenas irá verificar se o chamador imediato tem a permissão requerida. Já a segunda opção, Demand, executará a stack walk, ou seja, irá percorrer todos os elementos da stack, verificando se todos eles possuem a permissão solicitada.

Depois desta reestruturação (física ou virtual), a CLR irá assegurar (em tempo de execução) que o “código transparente” não poderá efetuar qualquer elevação de privilégios, garantindo que tudo o que o ele tentar executar, exigirá que toda a call stack tenha a respectiva permissão. E, para customizar a comportamento desta funcionalidade, a Microsoft disponibiliza alguns atributos:

  • SecurityTransparentAttribute: Somente permitido em nível de Assembly, diz ao runtime que ele será “transparente”, ou seja, não poderá executar qualquer ação que exija a elevação de privilégios. É importante dizer que “código transparente” não pode invocar “código crítico”.
  • SecurityCriticalAttribute: Quando utilizado em nível de Assembly, indica que ele pode ter “código crítico”. Isso vai depender da opção que você define ao utilizar o enumerador SecurityCriticalScope. A opção Everything indica que todo o código será considerado “código crítico”, enquanto a opção Explicit, determina que somente o membro onde o atributo está sendo aplicado será considerado como “código crítico”.
  • SecurityTreatAsSafeAttribute: Indica que o membro onde este atributo está sendo aplicado, pode ser acessado por outros membros que estão marcados com os atributos SecurityTransparentAttribute ou AllowPartiallyTrustedCallersAttribute. Não há nenhuma validação que evite a compilação quando você aplica este atributo em métodos públicos, e se você fizer isso, estes membros podem ser acessados através do “código transparente” tendo ter possíveis vulnerabilidades.

No exemplo abaixo, estamos definindo o atributo SecurityCriticalAttribute em nível de Assembly, dizendo que ele poderá conter “código crítico”. Com isso, somos obrigados a determinar qual método será “crítico”, utilizando o atributo SecurityCriticalAttribute ou o SecurityTreatAsSafeAttribute. Neste caso, optamos pela segunda opção, pois desejarmos que o método ReadFile possa ser invocado a partir de membro internos bem como externos, e com a configuração abaixo, será considerado “transparente”, e sem este atributo não seria possível.

[assembly: SecurityCritical]

static void Main(string[] args)
{
    Console.WriteLine(ReadFile());
}

[SecurityCritical]
[SecurityTreatAsSafeAttribute] 
private static string ReadFile(string filename)
{
    new FileIOPermission(FileIOPermissionAccess.Read, filename).Assert();
    //Ler o arquivo
}

Tags: ,

Security

IIS, WCF e Partial Trust

by Israel Aece 9. July 2009 11:39

Há algum tempo eu falei sobre a possibilidade de invocar serviços WCF em aplicações parcialmente confiáveis. Mas ainda há um segundo cenário, que é a exposição de serviços através de aplicações ASP.NET Web Site/WCF Service. Para criar um serviço WCF, você não precisa necessariamente criar um tipo de projeto exclusivo como o WCF Service. Um projeto do tipo ASP.NET Web Site pode, tranquilamente, servir como host de um serviço WCF, e para isso, basta adicionar um arquivo *.svc e configurá-lo corretamente no Web.config.

Independentemente de qual das alternativas utilize, você poderá se deparar com uma restrição de segurança, e dependendo das funcionalidades (mais precisamente do binding e seus elementos) que utiliza, o serviço não rodará. Isso muitas vezes acontece quando você faz o deployment para um servidor, em que a configuração padrão do .NET Framework foi alterada (visando uma maior segurança). Uma das regras mais importantes que se deve ter ao configurar um servidor Web (IIS), é não permitir que as aplicações que rodem ali executem em "Full Trust". Para isso, se altera o arquivo Web.config (que está em nível de servidor), definindo o atributo level do elemento trust para "Medium" ou qualquer nível abaixo disso.

Neste ambiente, você poderá utilizar os bindings BasicHttpBinding, WSHttpBinding ou o WebHttpBinding, desde que eles estejam com a segurança desabilitada ou com a proteção em nível de transporte. O binding WSDualHttpBinding também não pode ser utilizado neste cenário, já que algumas tarefas que ele desempenha exige um nível de segurança mais elevado. Finalmente, para tentar resolver este problema, podemos fazer uso das técnicas mostradas pelo Juval Lowy neste artigo, disponibilizando alguns helpers para facilitar a criação de hosts em ambientes parcialmente confiáveis.

Tags: , ,

Security | WCF

requirePermission

by Israel Aece 22. January 2009 15:11

As seções connectionStrings e appSettings são as únicas que podemos acessar diretamente no código sem nenhum tipo de problema, mesmo quando a aplicação está sendo executada em um ambiente parcialmente confiável. Por parcialmente confiável em uma uma aplicação ASP.NET, entenda como o trust level esteja definido como "Medium" ou algo abaixo disso:

<trust level="Medium"/>

Neste caso, qualquer outra seção (authentication, smtp, globalization, etc.) que tentarmos acessar em um neste ambiente, uma exceção do tipo SecurityException será lançada informando que não possuímos a permissão necessária que, neste caso, é ConfigurationPermission. Note que só o fato de acessar a seção já provoca o disparo da exceção:

AuthenticationSection section =
    (AuthenticationSection)WebConfigurationManager.GetSection("system.web/authentication");
Response.Write(section.Mode.ToString());

Quem determina essa restrição é o atributo requirePermission que é configurado no registro da seção dentro do arquivo de configuração. Por padrão, ele é definido como True e, como dito acima, somente as seções connectionStrings e appSettings são definidas como False, como se pode notar no arquivo machine.config. Somente altere a configuração padrão caso voce realmente saiba o que está fazendo e, principalmente, conhecendo as implicações que isso pode causar. Além disso, é importante dizer que voce também pode determinar essa restrição quando voce cria uma seção de configuração customizada.

Tags: ,

.NET Framework | ASP.NET | Security

Melhorias no WCF com SP1

by Israel Aece 14. August 2008 11:15

O Service Pack 1 do .NET Framework 3.5 e o Serviço Pack 1 do Visual Studio 2008 trouxeram algumas melhorias interessantes no WCF:

  • UriTemplate: agora podemos incluir um valor padrão para algum parametro que será invocado via REST. Algo como: [WebGet(UriTemplate = "RecuperarUsuarios/{quantidade=5}")].
  • Atributo DataContract/DataMember: a partir de agora não precisamos explicitamente definir quais são os objetos e propriedades que serão expostos para serviços quando estamos trabalhando com tipos complexos. Ele entende que tudo será exposto. Temos apenas que nos preocuparmos em marcar o que não queremos que seja serializado.
  • Partial Trust: possibilidade de fazer o uso do Event Log em ambiente parcialmente confiável.
  • Hosting Wizard: basicamente é a mesma funcionalidade do "Publish Web Site", mas para um serviço WCF.
  • WCF Options: quando tem um projeto do tipo Wcf Service Library na solução, nas propriedades deste projeto temos uma aba chamada WCF Options. Dentro da mesma, há uma opção chamada: Start WCF Service Host when debugging another project in the same solution. Ao marcá-la, ao rodar qualquer projeto em modo de depuração, o WCF Test Client irá iniciar para tornar o serviço disponível para que outras aplicações na mesma solução o utilizem.

Tags: , , ,

CSD | WCF

WCF - Partial Trust

by Israel Aece 6. May 2008 14:41

Uma das configurações mais importantes que se deve realizar em uma aplicação é a segurança, mais precisamente, que tipo de permissão devemos conceder à mesma para que ela possa ser executada. O tipo de permissão que me refiro aqui não tem a ver com a identidade do usuário, mas sim as permissões que o código (Assembly) tem para acessar recursos da máquina onde o mesmo está sendo executado.

Esse tipo de configuração foi introduzida desde a primeira versão do .NET Framework e é chamada de Code Access Security - CAS. Baseada no conceito de permissões, onde cada uma delas mapeia para um recurso (Message Queue, File System, SQL Server, etc.) da máquina, são através destas permissões que dizemos ao Runtime Security Policy (de forma declarativa ou imperativa), quais direitos nosso código tem de executar, ou melhor, a quais recursos ele terá acesso.

Se você cria qualquer aplicação .NET e não altera nenhuma configuração de segurança, ele será executado em Full Trust, ou seja, terá acesso irrestrito a qualquer recurso da máquina onde está atualmente sendo executado. Apesar disso ser muito comum, não é ideal. Uma premissa básica na segurança é jamais conceder direitos desnecessários a um código para desempenhar suas funções. Quando você opta por mudar a segurança padrão imposta pelo .NET, quer dizer que você está executando a aplicação em Partial Trust, ou seja, em um ambiente em que você não terá acesso a todos os recursos, mas sim, o essencial para a aplicação poder trabalhar.

Na primeira versão do WCF (Windows Communication Foundation) - .NET Framework 3.0 - ele não era suportado em ambientes que estavam sob Partial Trust, o que obrigava muitos clientes a conceder mais direitos do que o necessário para poder executar/invocar um serviço escrito em WCF. Depois de muitas requisições, a Microsoft decidiu afrouxar essa segurança com o lançamento do .NET Framework 3.5, permitindo (com várias restrições) que serviços sejam invocados a partir de um ambiente parcialmente confiável. Isso obrigou a Microsoft a decorar os assemblies System.ServiceModel.dll e System.ServiceModel.Web.dll com o atributo AllowPartiallyTrustedCallers que, como o nome diz, permite que o assembly seja invocado por aplicações que estão sendo executadas em um ambiente mais restrito.

Entre as limitações que o WCF 3.5 impõe, temos: permite somente os bindings BasicHttpBinding, WsHttpBinding (sem segurança ou com segurança a nível de transporte) e WebHttpBinding serem invocados a partir de uma aplicação que está sendo executada em ambiente parcialmente confiável; além disso, serviços WCF que estão rodando em aplicações de middle tier também podem invocar requisições para outros serviços, desde que tenha a sua respectiva WebPermisson, que concede direito de acesso a esse recurso. Todos os outros bindings, não HTTP, demandarão full trust de seus chamadores, obrigando-nos a conceder ao cliente mais direitos do que ele deveria ter para poder trabalhar. Para uma lista completa de todas as restrições, você pode consultar este link.

Mas e quando necessitamos referenciar em nossa aplicação parcialmente confiável, um serviço WCF que expõe apenas um endpoint com o binding definido como NetTcpBinding? Uma alternativa interessante é criar um proxy, isolando toda a chamada para este serviço. E no que consiste um proxy? Basicamente trata-se de uma DLL que conterá uma classe que servirá como um wrapper para a interface do serviço a ser acessado. Quando referenciamos o serviço diretamente na aplicação, automaticamente a IDE do Visual Studio se encarrega de criar a classe (também denominada proxy) para que possamos invocar os respectivos métodos do serviço localmente e que, durante a execução, será delegado ao serviço.

Para o nosso cenário isso não será a melhor saída. O que devemos fazer é utilizar o utilitário svcutil.exe que, entre suas utilidades, é capaz de gerar uma classe baseado no WSDL extraído do mesmo. A linha abaixo ilustra como devemos passar os parâmetros para o svcutil.exe para que o mesmo possa gerar a classe correspondente (executando a partir do prompt do Visual Studio .NET):

C:\>svcutil net.tcp://localhost:9000/Mex /out:C:\Proxy.cs

Uma vez que a classe é criada, criaremos um projeto do tipo Class Library e adicionaremos a classe recém criada, Proxy.cs, dentro deste projeto. Além disso, é também necessário fazer a referência para o assembly System.ServiceModel.dll. Depois deste processo, precisamos ainda fazer algumas configurações em nível de assembly; como essa DLL deverá ser consumida por um projeto que está sendo executado em um ambiente parcialmente confiável, adicionar no arquivo AssemblyInfo.cs o atributo AllowPartiallyTrustedCallers; finalmente, será necessário definir um Strong Name para essa DLL (veremos mais tarde, ainda neste artigo o motivo disso). O trecho de código abaixo ilustra como devemos proceder para definir o atributo APTCA:

using System.Security;

[assembly: AllowPartiallyTrustedCallers]

Para finalizar, é necessário abrir o arquivo Proxy.cs e, no ínicio da classe que representa o serviço do lado do cliente (ClientBase), e especificar o atributo PermissionSetAttribute, assim como é mostrado abaixo:

using System.Security;
using System.Security.Permissions;

[PermissionSetAttribute(SecurityAction.Assert, Name = "FullTrust")]
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1
{
    //Implementação
}

O atributo PermissionSetAttribute irá permitir a definição de uma determinada ação para uma permission set (conjunto de permissões) específica. No exemplo acima, estamos especificando a ação Assert (via enumerador SecurityAction) sob a permission set predefinida, que é a FullTrust. A utilização da ação/método Assert deve ser analisada com muito cuidado, pois é o mesmo que "Eu sei o que estou fazendo; confie em mim!", e isso garantirá que a permissão seja concedida ao chamador mesmo que ele não tenha privilégio para isso.

Finalmente, a DLL está pronta para ser utilizada mas se, neste momento, a mesma for referenciada na aplicação que está sendo executada em ambiente parcialmente confiável, uma exceção será atirada, dizendo que não é possível consumir um serviço via TCP nesta aplicação. Neste caso, necessitamos adicionar essa DLL no GAC, pois os componentes que lá residem já ganham Full Trust. É importante dizer que, mesmo assim, é necessário o código acima, pois o stack walk também verificará a aplicação Web que chama o componente e essa, por sua vez, não terá a permissão necessária e, consequentemente, a exceção será atirada. Esse conceito que utilizamos aqui também é conhecido como Sandboxing.

Importante: Apesar desta técnica funcionar, ela tem um ponto negativo: suprimindo a security demand, que é o processo de avaliação dos chamadores para se certificar que todos possuem tal permissão, permitirá que qualquer cliente que execute sob ambiente parcialmente confiável chame qualquer serviço WCF. Isso permitirá a um cliente que não tenha permissão de acesso a algum recurso, como acesso TCP, aplicar um bypass nesta limitação. A solução para esse problema é criar uma classe que herde diretamente da classe base ClientBase, concedendo as permissões específicas, dependendo do tipo de binding.

Conclusão: Felizmente o WCF permite na versão 3.5 do .NET Framework o consumo de serviços em ambiente parcialmente confiáveis. Alguns bindings podem ser consumidos sem a necessidade de alguma configuração adicional, pois são acessíveis em ambientes parcialmente confiáveis; já outros bindings não podem ser acessados diretamente, e necessitam de um passo adicional, que é a criação do proxy, explicado neste artigo.

Tags: ,

CSD | Security | WCF

Powered by BlogEngine.NET 1.5.0.0
Theme by Mads Kristensen

Sobre

Meu nome é Israel Aece e sou especialista em tecnologias de desenvolvimento Microsoft, atuando como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. [ Mais ]

Twitter

Indicações

Introdução ao ASP.NET Web API - e-Book