2017-04-18 7 views
1

HTTPS를 통해 WCF 서비스를 호출하고 있습니다. => 인증서는 정상입니다. 스크린 샷보기 : enter image description here서비스 패브릭에서 HTTPS를 통해 WCF 호출 : 요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다.

클라이언트 인증서가 내 계정 및 로컬 컴퓨터에 설치되어 있습니다. 두 가지 모두 내보낼 수 있습니다.

그래서 콘솔 응용 프로그램에서 작동하는 코드 조각이 있습니다. 네트워크 서비스에서 콘솔 앱을 실행하면 서비스 호출이 작동합니다.

이 코드를 StatefullService (서비스 패브릭 내부)에 붙여 넣으면 다음과 같은 예외가 발생합니다.

콘솔 응용 프로그램 및 서비스 fabcric에서 ServicePointManager.SecurityProtocolSystem.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12을 확인했습니다.

"System.ServiceModel.Security.SecurityNegotiationException '. ******** cloudapp.azure.com을'. 권위 SSL/TLS에 대한 보안 채널을 설정할 수 없습니다 ---> System.Net .WebException : 요청이 중단되었습니다 : SSL/TLS 보안 채널을 만들 수 없습니다. System.Net.HttpWebRequest.GetResponse() \ r \ n (System.ServiceModel.Channels.HttpChannelFactory 1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)\r\n --- End of inner exception stack trace ---\r\n\r\nServer stack trace: \r\n at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)\r\n at System.ServiceModel.Channels.HttpChannelFactory)에서 1.HttpRequestChannel.HttpChannelRequest. System.ServiceModel.Channels.RequestChannel.Request (메시지 메시지, TimeSpan 시간 초과)에서 \ WaitForReply (TimeSpan 시간 초과) \ r \ n System.ServiceModel.Dispatcher.RequestChannelBinder.Request (메시지 메시지, TimeSpan 시간 초과) System.ServiceModel.Channels.ServiceChannel.Call (String 동작, 부울 oneway, ProxyOperationRuntime 작업, Object [] ins, Object [] 출력, TimeSpan 시간 초과)에서 \ n \ System \ System \ rviceModel.Channels.ServiceChannelProxy.InvokeService (IMethodCallMessage methodCall, ProxyOperationRuntime 작업) \ r \ n System.ServiceModel.Channels.ServiceChannelProxy.Invoke (IMessage 메시지) \ r \ n \ r \ n 예외는 [0]에서 재개됩니다. \ r \ n System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage (IMessage reqMsg, IMessage retMsg) \ System \ Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData & msgData, Int32 유형)에서 \ r \ n ** ********************************* \ r \ n at ************ **************************************** cs : line 75 \ r \ n at ****************************************** * .cs : 34 행 34 \ r \ n *********************************** . ******** CS : 라인 (20) "

코드는 다음



      var binding = new BasicHttpBinding(); 
      binding.Security.Mode = BasicHttpSecurityMode.Transport; 
      binding.Security.Transport = new HttpTransportSecurity 
      { 
       ClientCredentialType = HttpClientCredentialType.Certificate, 
      }; 
      string endpoint = "https://********.cloudapp.azure.com/*****/SomeService.svc"; 
      var endpoint1 = new EndpointAddress(endpoint); 

      var factory = new ChannelFactory(binding, endpoint); 

      var clientCredentials = new ClientCredentials(); 
      clientCredentials.ClientCertificate.SetCertificate("CN=my-cn-name", 
       System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, 
       System.Security.Cryptography.X509Certificates.StoreName.My); 

      if (factory.Endpoint.EndpointBehaviors.Contains(typeof(ClientCredentials))) 
      { 
       factory.Endpoint.EndpointBehaviors.Remove(typeof(ClientCredentials)); 
      } 

      factory.Endpoint.EndpointBehaviors.Add(clientCredentials); 

      var channel = factory.CreateChannel(); 

      try 
      { 
       var result = channel.GetData(1); 

       Console.WriteLine("Success"); 
       Console.ReadLine(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
       Console.ReadLine(); 
      } 

서비스 패브릭의 HTTPS를 통해 WCF 서비스를 호출하지 못했습니다. HTTPS 프로토콜을 사용하지 않도록 설정하고 기존 WCF 서비스에서 HTTP 프로토콜을 사용하도록 설정하면 연결할 수 있습니다. 그러나 분명한 이유로 우리는 HTTPS가 필요합니다.

편집 한 테스트

:

이 콘솔 응용 프로그램도 작동하는 HTML을받을 GET으로 HttpClient를하고 WebRequestHandler와 서비스 호출
  1. . 서비스 기능이없는 구조.
  2. 개인 저장소에서 인증서를 제거했습니다. 콘솔 응용 프로그램은 로컬 컴퓨터 저장소를 사용하기 때문에 계속 작동합니다 (위 코드 샘플 참조).
  3. HTTPS를 통해 우편 배달부에서 SOAP 요청을 처리합니다.

(네트워크 서비스)이 응답 https://serverfault.com/a/132791/135762 다음 편집 2

작동했다.

답변

0

문제는 네트워크 서비스 계정에 인증서의 개인 키에 액세스 할 수있는 올바른 액세스 권한이 없다는 것입니다.

두 가지 방법으로 해결할 수 있습니다.

처음에는 인증서를 설치하고 구성하기 위해 powershell과 setup.bat를 사용하십시오.

서비스 패브릭 서비스에서 프로젝트의 루트에 Setup.bat를 추가하십시오. 편집 서비스 매니페스트와는 설치 진입 점

<ExeHost> <Program>Setup.bat</Program> <WorkingFolder>CodePackage</WorkingFolder> </ExeHost>

박쥐 파일 아마 높은 신뢰로 실행해야합니다을 추가합니다. 당신은 ServiceManifestImport 안에는 응용 프로그램 매니페스트 에 다음을 추가 할 수 있습니다

(는 XML의 루트에) 응용 프로그램 매니페스트의 하단에서

<Policies> <RunAsPolicy CodePackageRef="Code" UserRef="SetupAdminUser" EntryPointType="Setup" /> </Policies>

가 관리자로 실행하려면 다음을 추가합니다. <Principals> <Users> <User Name="SetupAdminUser"> <MemberOf> <SystemGroup Name="Administrators" /> </MemberOf> </User> </Users> </Principals>

박쥐 파일은 간단하다 : (우리는 자체 서명 된 인증서를 사용하기 때문에) powershell.exe -ExecutionPolicy Bypass -Command ".\Scripts\Install-Certificates.ps1"

파워 쉘 스크립트는이 신뢰할 수있는 루트 저장소에 인증서를 설치합니다이


$pwd = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText 

function Set-CertificatePermission 
{ 
param 
(
    [Parameter(Position=1, Mandatory=$true)] 
    $cert , 

    [Parameter(Position=2, Mandatory=$true)] 
    [ValidateNotNullOrEmpty()] 
    [string]$serviceAccount 
) 


# Specify the user, the permissions and the permission type 
$permission = "$($serviceAccount)","Read,FullControl","Allow" 
$accessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission; 

# Location of the machine related keys 
$keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\"; 
$keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName; 
$keyFullPath = $keyPath + $keyName; 

try 
{ 
    # Get the current acl of the private key 
    $acl = (Get-Acl $keyFullPath) 

    # Add the new ace to the acl of the private key 
    $acl.AddAccessRule($accessRule); 

    # Write back the new acl 
    Set-Acl -Path $keyFullPath -AclObject $acl; 
} 
catch 
{ 
    throw $_; 
} 
} 

function Install-RootCA($path){ 
    Write-Host "Installing root certificate" 

    Import-PfxCertificate -FilePath $path -CertStoreLocation "Cert:\LocalMachine\Root" -Password $pwd -Exportable 
} 

function Install-Certificate($path){ 
    Write-Host "Installing certificate" 

    $cert = Import-PfxCertificate -FilePath $path -CertStoreLocation "Cert:\LocalMachine\My" -Password $pwd -Exportable 
    Set-CertificatePermission $cert "NT AUTHORITY\NETWORK SERVICE" 
} 



Install-RootCA ".\Certificates\CARoot.pfx" 
Install-Certificate ".\Certificates\ClientCert.pfx" 

처럼 보일 수 있습니다 컴퓨터 계정의 개인 저장소에 인증서를 설치하십시오. Service Fabric의 중요한 비트는 네트워크 서비스가 액세스하는 개인 키에 대한 올바른 권한을 설정한다는 것입니다.

두 번째 방법 : 마누엘는

  • 컴퓨터 계정
  • 을 선택려고 달려 드는는
  • 인증서를 추가, 제거 => 프로그램 추가/MMC

    1. 를 눌러 Windows 키 + R
    2. mmc를 입력
    3. 파일을 사용하여
    4. 신뢰할 수있는 루트 인증 기관 \ 인증서를 마우스 오른쪽 단추로 클릭 한
    5. 가져 오기 루트 인증서 *의 .PFX (마크가로 내보낼 수)
    6. 오른쪽 * 클라이언트 인증서를 개인 \ 인증서
    7. 가져 오기를 클릭합니다.PFX (마크가로 내보낼 수) 가져온 클라이언트 인증서에
    8. 오른쪽 클릭 : 모든 작업은 =>
    9. 제 3의 방법이있는 사용자로 네트워크 서비스를 추가하고 모든 권한
  • 0

    을주고 개인 키 관리 이는 WCF에서 작동해야하는 위의 것보다 간단합니다. 이 서비스가 네트워크 서비스 계정에서 실행중인 경우 "protocol = https"를 다음과 같이 서비스 끝점 선언에 넣을 수 있습니다.

    <Resources> 
        <Endpoints> 
        <Endpoint Name="ServiceEndpoint" Protocol="https" /> 
    </Endpoints> 
    

    선택적으로 당신은 클라이언트에 인증서를 반환 할 수 있으며, 다른 보안 권한에 따라이 서비스를 실행합니다. 자세한 내용은 여기를 참조하십시오. https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-application-runas-security#assign-a-security-access-policy-for-http-and-https-endpoints

    관련 문제