none
SSIS para CRM 2011 com ADFS RRS feed

  • Pergunta

  • Olá, galera.

    Gostaria de ajuda para adaptar o proxy de conexão do SSIS com os seviços do CRM 2011 via ADFS.

    Desde já agradeço pelas respostas.

    quarta-feira, 10 de outubro de 2012 18:09

Todas as Respostas

  • Isaias,

    No final das contas precisa de uma classe autenticadora do CRM 2011 via ADFS, pode usar este exemplo para se comunicar:

    http://tiagomcardoso.wordpress.com/2012/06/12/crm-2011-acessar-web-service/

    Att,


    Tiago Michelini Cardoso MVP - MCC - MCTS
    https://tiagomcardoso.wordpress.com/

    quarta-feira, 10 de outubro de 2012 18:33
    Moderador
  • Boa tarde, Tiago.

    Obrigado pela a resposta. Mas estou com dificuldade de acessar os serviços, Discovery e Organization, do CRM 2011, via ADFS, para trabalhar com SSIS (framework 3.5) fazendo uso de proxy.

    quarta-feira, 10 de outubro de 2012 21:48
  • Ok Isaias,

    Onde está o seu problema? Não está obtendo a autenticação? Não conseguiu implementar o código? 

    Att,


    Tiago Michelini Cardoso MVP - MCC - MCTS
    https://tiagomcardoso.wordpress.com/

    segunda-feira, 15 de outubro de 2012 14:02
    Moderador
  • Boa tarde, Tiago.

    Obrigado pela resposta.

    Bom, acho que seja na mecânica de autenticação do usuário.
    Antes, estava usando o seguinte código para configurar e acessar o webservice do CRM, Organization.svc, no SSIS com o protocolo http:

     public static IOrganizationService GetCRMService(string ServerHost, string OrgName, string UserName, string Domain, string Pwd)
            {
                Uri organizationUri = new Uri(string.Format("{0}/{1}/XRMServices/2011/Organization.svc?wsdl", ServerHost, OrgName));
    
                SymmetricSecurityBindingElement security = new SymmetricSecurityBindingElement();
                security.ProtectionTokenParameters = new SspiSecurityTokenParameters();
    
                HttpTransportBindingElement htbe = new HttpTransportBindingElement();
                htbe.MaxReceivedMessageSize = 1000000000;
    
                CustomBinding binding = new CustomBinding();
                binding.Elements.Add(security);
                TextMessageEncodingBindingElement tmebe = new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8);
                binding.Elements.Add(tmebe);
                binding.Elements.Add(htbe);
    
                EndpointAddress address = new EndpointAddress(organizationUri, EndpointIdentity.CreateUpnIdentity(string.Format("{0}@{1}", UserName, Domain)), new AddressHeader[] { });
    
                OrganizationServiceClient osclient = new OrganizationServiceClient(binding, address);
                osclient.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(UserName, Pwd, Domain);
    
                return (IOrganizationService)osclient;
            }

    Mas com a implantação do ADFS este código não dar suporte a integração do SSIS com o serviço do CRM 2011. E através de varias pesquisas fiz vários testes mas sem sucesso.
    Tiago, gostaria de ajuda para fazer este código funcionar com ADFS (https).

    segunda-feira, 15 de outubro de 2012 19:21
  • Isaias,

    Veja um exemplo, nele tenho ao meu ver todos os tipos de autenticação Live ID, AD e Federation, aqui também usamos ADFS, e esta classe faz a conexão sem problemas:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Reflection;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    using Microsoft.Xrm.Sdk.Discovery;
    using System.Net;
    using System.Text;
    using System.Collections;
    using System.Configuration;
    
    namespace Autenticacao
    {
        public class Autenticacao
        {
            public Autenticacao(string organization)
            {
                _organizationUniqueName = organization;
                _discoveryServiceAddress = "https://URL_CRM/XRMServices/2011/Discovery.svc";
            }
    
            // Variáveis auxiliares
            private String _organizationUniqueName;
            private String _discoveryServiceAddress;
            private String _userName = "USER";
            private String _password = "PASSWORD";
            private String _domain = "DOMAIN";
    
            // OrganizationServiceProxy responsável pelo acesso ao WCF do CRM
            private OrganizationServiceProxy _organizationProxy = null;
            public OrganizationServiceProxy organizationProxy
            {
                get
                {
                    if (_organizationProxy == null)
                        _organizationProxy = GetProxy<IOrganizationService, OrganizationServiceProxy>(orgServiceManagement, credentials);
    
                    return _organizationProxy;
                }
            }
            //
    
            private IServiceManagement<IOrganizationService> _orgServiceManagement = null;
            private IServiceManagement<IOrganizationService> orgServiceManagement
            {
                get
                {
                    if (_orgServiceManagement == null)
                        _orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(organizationUri));
    
                    return _orgServiceManagement;
                }
            }
    
            private AuthenticationCredentials _credentials = null;
            private AuthenticationCredentials credentials
            {
                get
                {
                    if (_credentials == null)
                        _credentials = GetCredentials(endpointType);
    
                    return _credentials;
                }
            }
    
            private IServiceManagement<IDiscoveryService> _serviceManagement = null;
            private IServiceManagement<IDiscoveryService> serviceManagement
            {
                get
                {
                    if (_serviceManagement == null)
                        _serviceManagement = ServiceConfigurationFactory.CreateManagement<IDiscoveryService>(new Uri(_discoveryServiceAddress));
    
                    return _serviceManagement;
                }
            }
    
            private AuthenticationProviderType _endpointType = AuthenticationProviderType.Federation;//ActiveDirectory;
            private AuthenticationProviderType endpointType
            {
                get
                {
                    if (_endpointType == AuthenticationProviderType.None)
                        _endpointType = serviceManagement.AuthenticationType;
    
                    return _endpointType;
                }
            }
    
            private AuthenticationCredentials _authCredentials = null;
            private AuthenticationCredentials authCredentials
            {
                get
                {
                    if (_authCredentials == null)
                        _authCredentials = GetCredentials(endpointType);
    
                    return _authCredentials;
                }
            }
    
            private String _organizationUri = String.Empty;
            private string organizationUri
            {
                get
                {
                    if (_organizationUri == String.Empty)
                    {
                        using (DiscoveryServiceProxy discoveryProxy = GetProxy<IDiscoveryService, DiscoveryServiceProxy>(serviceManagement, authCredentials))
                        {
                            if (discoveryProxy != null)
                            {
                                OrganizationDetailCollection orgs = DiscoverOrganizations(discoveryProxy);
    
                                _organizationUri = FindOrganization(_organizationUniqueName, orgs.ToArray()).Endpoints[EndpointType.OrganizationService];
                            }
                        }
                    }
    
                    return _organizationUri;
                }
            }
    
            private ClientCredentials _credencial = null;
            private ClientCredentials Credencials
            {
                get
                {
                    if (_credencial == null)
                    {
                        _credencial = new ClientCredentials();
                        _credencial.Windows.ClientCredential = new NetworkCredential(_userName, _password);
                    }
    
                    return _credencial;
                }
            }
    
            /// <summary>
            /// Obtain the AuthenticationCredentials based on AuthenticationProviderType.
            /// </summary>
            /// <param name="endpointType">An AuthenticationProviderType of the CRM environment.</param>
            /// <returns>Get filled credentials.</returns>
            private AuthenticationCredentials GetCredentials(AuthenticationProviderType endpointType)
            {
    
                AuthenticationCredentials authCredentials = new AuthenticationCredentials();
                switch (endpointType)
                {
                    case AuthenticationProviderType.ActiveDirectory:
                        authCredentials.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(_userName, _password, _domain);
                        break;
                    case AuthenticationProviderType.LiveId:
                        authCredentials.ClientCredentials.UserName.UserName = _userName;
                        authCredentials.ClientCredentials.UserName.Password = _password;
                        authCredentials.SupportingCredentials = new AuthenticationCredentials();
                        authCredentials.SupportingCredentials.ClientCredentials = Microsoft.Crm.Services.Utility.DeviceIdManager.LoadOrRegisterDevice();
                        break;
                    default: // For Federated and OnlineFederated environments.                    
                        authCredentials.ClientCredentials.UserName.UserName = _userName;
                        authCredentials.ClientCredentials.UserName.Password = _password;
                        // For OnlineFederated single-sign on, you could just use current UserPrincipalName instead of passing user name and password.
                        // authCredentials.UserPrincipalName = UserPrincipal.Current.UserPrincipalName;  //Windows/Kerberos
                        break;
                }
    
                return authCredentials;
            }
    
            /// <summary>
            /// Discovers the organizations that the calling user belongs to.
            /// </summary>
            /// <param name="service">A Discovery service proxy instance.</param>
            /// <returns>Array containing detailed information on each organization that 
            /// the user belongs to.</returns>
            private OrganizationDetailCollection DiscoverOrganizations(IDiscoveryService service)
            {
                if (service == null) throw new ArgumentNullException("service");
                RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
                RetrieveOrganizationsResponse orgResponse = (RetrieveOrganizationsResponse)service.Execute(orgRequest);
    
                return orgResponse.Details;
            }
    
            /// <summary>
            /// Finds a specific organization detail in the array of organization details
            /// returned from the Discovery service.
            /// </summary>
            /// <param name="orgUniqueName">The unique name of the organization to find.</param>
            /// <param name="orgDetails">Array of organization detail object returned from the discovery service.</param>
            /// <returns>Organization details or null if the organization was not found.</returns>
            /// <seealso cref="DiscoveryOrganizations"/>
            private OrganizationDetail FindOrganization(string orgUniqueName, OrganizationDetail[] orgDetails)
            {
                if (String.IsNullOrWhiteSpace(orgUniqueName))
                    throw new ArgumentNullException("orgUniqueName");
                if (orgDetails == null)
                    throw new ArgumentNullException("orgDetails");
                OrganizationDetail orgDetail = null;
    
                foreach (OrganizationDetail detail in orgDetails)
                {
                    //if (String.Compare(detail.UniqueName, orgUniqueName, StringComparison.InvariantCultureIgnoreCase) == 0)
                    if (String.Compare(detail.UrlName, orgUniqueName, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        orgDetail = detail;
                        break;
                    }
                }
                return orgDetail;
            }
    
            /// <summary>
            /// Generic method to obtain discovery/organization service proxy instance.
            /// </summary>
            /// <typeparam name="TService">
            /// Set IDiscoveryService or IOrganizationService type to request respective service proxy instance.
            /// </typeparam>
            /// <typeparam name="TProxy">
            /// Set the return type to either DiscoveryServiceProxy or OrganizationServiceProxy type based on TService type.
            /// </typeparam>
            /// <param name="serviceManagement">An instance of IServiceManagement</param>
            /// <param name="authCredentials">The user's Microsoft Dynamics CRM logon credentials.</param>
            /// <returns></returns>
            private TProxy GetProxy<TService, TProxy>(IServiceManagement<TService> serviceManagement, AuthenticationCredentials authCredentials)
                where TService : class
                where TProxy : ServiceProxy<TService>
            {
                Type classType = typeof(TProxy);
    
                if (serviceManagement.AuthenticationType != AuthenticationProviderType.ActiveDirectory)
                {
                    AuthenticationCredentials tokenCredentials = serviceManagement.Authenticate(authCredentials);
                    // Obtain discovery/organization service proxy for Federated, LiveId and OnlineFederated environments. 
                    // Instantiate a new class of type using the 2 parameter constructor of type IServiceManagement and SecurityTokenResponse.
    
                    return (TProxy)classType
                        .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(SecurityTokenResponse) })
                        .Invoke(new object[] { serviceManagement, tokenCredentials.SecurityTokenResponse });
                }
    
                // Obtain discovery/organization service proxy for ActiveDirectory environment.
                // Instantiate a new class of type using the 2 parameter constructor of type IServiceManagement and ClientCredentials.
                return (TProxy)classType
                    .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(ClientCredentials) })
                    .Invoke(new object[] { serviceManagement, authCredentials.ClientCredentials });
            }
        }
    }

    Note que existe uma parte hard code, como o login, senha e etc, troque isso pelo que achar mais conveniente.

    Att,


    Tiago Michelini Cardoso MVP - MCC - MCTS
    https://tiagomcardoso.wordpress.com/


    quarta-feira, 17 de outubro de 2012 12:57
    Moderador
  • Bom dia, Tiago.

    Obrigado pela resposta.

    Gostaria de saber, como dar suporte ao codigo acima para funcionar com o FrameWork 3.5 (SSIS 2008).

    Isaias Silva

    quinta-feira, 18 de outubro de 2012 14:56
  • Se for complicado alterar, crie em um projeto separado, gere uma dll e depois importe no SSIS. Ou exponha através de um serviço...

    Tiago Michelini Cardoso MVP - MCC - MCTS
    https://tiagomcardoso.wordpress.com/

    quinta-feira, 18 de outubro de 2012 17:22
    Moderador
  • Boa tarde, Tiago.

    Obrigado pela resposta.

    O problema é que o SSIS 2008 trabalha com o  FrameWork 3.5, e neste framework não há suporte para as bibliotecas do XRM:

    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Client;
    using Microsoft.Xrm.Sdk.Discovery;

    Já fiz varios testes porém sem sucesso. Veja o erro:

    Warning 1 Resolved file has a bad image, no metadata, or is otherwise inaccessible. Could not load file or assembly '..\CrmAuthenticate.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. st_1ac6f54779764fa58f9054ea6bd80e64

    Esta dependencia é por causa das bibliotecas acima.

    Nota:  O código acima é funcional. O teste foi realizado através de app console, com o FrameWork 4.0, resultado foi bem sucedido.

    Isaias Silva


    quinta-feira, 18 de outubro de 2012 18:44