blob: 152d8feab98792087ce6fb8215cd79e46c85846a [file] [log] [blame]
Jan Tattermuscheea59552015-07-23 22:05:32 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015-2016 gRPC authors.
Jan Tattermuscheea59552015-07-23 22:05:32 -07004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
Jan Tattermuscheea59552015-07-23 22:05:32 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermuscheea59552015-07-23 22:05:32 -070010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
Jan Tattermuscheea59552015-07-23 22:05:32 -070016
17#endregion
18
19using System;
20using System.Collections.Generic;
21using System.IO;
Jan Tattermusch31ba0632015-08-04 22:02:55 -070022using System.Linq;
Jan Tattermuscheea59552015-07-23 22:05:32 -070023using System.Threading;
24using System.Threading.Tasks;
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -080025using Google.Protobuf;
Jan Tattermuscheea59552015-07-23 22:05:32 -070026using Grpc.Core;
27using Grpc.Core.Utils;
Jan Tattermusch8644aea2015-08-03 10:21:18 -070028using Grpc.Testing;
Jan Tattermuscheea59552015-07-23 22:05:32 -070029using NUnit.Framework;
30
31namespace Grpc.IntegrationTesting
32{
33 /// <summary>
34 /// Test SSL credentials where server authenticates client
35 /// and client authenticates the server.
36 /// </summary>
37 public class SslCredentialsTest
38 {
Jan Tattermusch31ba0632015-08-04 22:02:55 -070039 const string Host = "localhost";
Jan Tattermuscheea59552015-07-23 22:05:32 -070040 Server server;
41 Channel channel;
Jan Tattermusch809148d2016-03-22 15:09:41 -070042 TestService.TestServiceClient client;
Jan Tattermuscheea59552015-07-23 22:05:32 -070043
Jan Tattermuschc152d662017-08-09 09:24:20 +020044 [OneTimeSetUp]
Jan Tattermuscheea59552015-07-23 22:05:32 -070045 public void Init()
46 {
47 var rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath);
48 var keyCertPair = new KeyCertificatePair(
49 File.ReadAllText(TestCredentials.ServerCertChainPath),
50 File.ReadAllText(TestCredentials.ServerPrivateKeyPath));
51
Jan Tattermuschd27dfa72015-08-04 18:10:54 -070052 var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, true);
Jan Tattermuscheea59552015-07-23 22:05:32 -070053 var clientCredentials = new SslCredentials(rootCert, keyCertPair);
54
Jan Tattermusch09d2f552017-04-20 11:39:37 +020055 // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
56 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
Jan Tattermusch021df8a2015-08-04 20:31:11 -070057 {
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -080058 Services = { TestService.BindService(new SslCredentialsTestServiceImpl()) },
Jan Tattermusch31ba0632015-08-04 22:02:55 -070059 Ports = { { Host, ServerPort.PickUnused, serverCredentials } }
Jan Tattermusch021df8a2015-08-04 20:31:11 -070060 };
Jan Tattermuscheea59552015-07-23 22:05:32 -070061 server.Start();
62
63 var options = new List<ChannelOption>
64 {
65 new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
66 };
67
Jan Tattermusch31ba0632015-08-04 22:02:55 -070068 channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options);
Jan Tattermuschf41ebc32016-06-22 12:47:14 -070069 client = new TestService.TestServiceClient(channel);
Jan Tattermuscheea59552015-07-23 22:05:32 -070070 }
71
Jan Tattermuschc152d662017-08-09 09:24:20 +020072 [OneTimeTearDown]
Jan Tattermuscheea59552015-07-23 22:05:32 -070073 public void Cleanup()
74 {
Jan Tattermusch2b357952015-08-20 14:54:33 -070075 channel.ShutdownAsync().Wait();
Jan Tattermuscheea59552015-07-23 22:05:32 -070076 server.ShutdownAsync().Wait();
Jan Tattermuscheea59552015-07-23 22:05:32 -070077 }
78
79 [Test]
80 public void AuthenticatedClientAndServer()
81 {
Jan Tattermusch8644aea2015-08-03 10:21:18 -070082 var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 });
Jan Tattermuscheea59552015-07-23 22:05:32 -070083 Assert.AreEqual(10, response.Payload.Body.Length);
84 }
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -080085
86 [Test]
87 public async Task AuthContextIsPopulated()
88 {
89 var call = client.StreamingInputCall();
90 await call.RequestStream.CompleteAsync();
91 var response = await call.ResponseAsync;
92 Assert.AreEqual(12345, response.AggregatedPayloadSize);
93 }
94
95 private class SslCredentialsTestServiceImpl : TestService.TestServiceBase
96 {
Jan Tattermuschc152d662017-08-09 09:24:20 +020097 public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -080098 {
Jan Tattermuschc152d662017-08-09 09:24:20 +020099 return Task.FromResult(new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) });
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -0800100 }
101
102 public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
103 {
104 var authContext = context.AuthContext;
Jan Tattermuschc152d662017-08-09 09:24:20 +0200105 await requestStream.ForEachAsync(request => TaskUtils.CompletedTask);
Jan Tattermuschc9b03fe2017-02-06 08:45:00 -0800106
107 Assert.IsTrue(authContext.IsPeerAuthenticated);
108 Assert.AreEqual("x509_subject_alternative_name", authContext.PeerIdentityPropertyName);
109 Assert.IsTrue(authContext.PeerIdentity.Count() > 0);
110 Assert.AreEqual("ssl", authContext.FindPropertiesByName("transport_security_type").First().Value);
111
112 return new StreamingInputCallResponse { AggregatedPayloadSize = 12345 };
113 }
114
115 private static Payload CreateZerosPayload(int size)
116 {
117 return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
118 }
119 }
Jan Tattermuscheea59552015-07-23 22:05:32 -0700120 }
121}