Require very explicit registration of non-SSL hosts.

pull/2758/head
Jorge Canizales 9 years ago
parent 82b68d8a97
commit b2bd06775e
  1. 4
      src/objective-c/GRPCClient/GRPCCall+Tests.h
  2. 8
      src/objective-c/GRPCClient/GRPCCall+Tests.m
  3. 37
      src/objective-c/GRPCClient/private/GRPCHost.m
  4. 7
      src/objective-c/tests/GRPCClientTests.m
  5. 2
      src/objective-c/tests/InteropTests.h
  6. 10
      src/objective-c/tests/InteropTests.m

@ -33,6 +33,8 @@
#import "GRPCCall.h" #import "GRPCCall.h"
// Methods to let tune down the security of gRPC connections for specific hosts. These shouldn't be
// used in releases, but are sometimes needed for testing.
@interface GRPCCall (Tests) @interface GRPCCall (Tests)
// Establish all SSL connections to the provided host using the passed SSL target name and the root // Establish all SSL connections to the provided host using the passed SSL target name and the root
@ -42,4 +44,6 @@
testName:(NSString *)testName testName:(NSString *)testName
forHost:(NSString *)host; forHost:(NSString *)host;
// Establish all connections to the provided host using cleartext instead of SSL.
+ (void)useInsecureConnectionsForHost:(NSString *)host;
@end @end

@ -36,12 +36,18 @@
#import "private/GRPCHost.h" #import "private/GRPCHost.h"
@implementation GRPCCall (Tests) @implementation GRPCCall (Tests)
+ (void)useTestCertsPath:(NSString *)certsPath + (void)useTestCertsPath:(NSString *)certsPath
testName:(NSString *)testName testName:(NSString *)testName
forHost:(NSString *)host { forHost:(NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.secure = YES;
hostConfig.pathToCertificates = certsPath; hostConfig.pathToCertificates = certsPath;
hostConfig.hostNameOverride = testName; hostConfig.hostNameOverride = testName;
} }
+ (void)useInsecureConnectionsForHost:(NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.secure = NO;
}
@end @end

@ -58,22 +58,12 @@
// Default initializer. // Default initializer.
- (instancetype)initWithAddress:(NSString *)address { - (instancetype)initWithAddress:(NSString *)address {
// Verify and normalize the address, and decide whether to use SSL. // To provide a default port, we try to interpret the address.
if (![address rangeOfString:@"://"].length) { // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass through.
// No scheme provided; assume https. NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]];
address = [@"https://" stringByAppendingString:address]; if (hostURL && !hostURL.port) {
address = [hostURL.host stringByAppendingString:@":443"];
} }
NSURL *hostURL = [NSURL URLWithString:address];
if (!hostURL) {
[NSException raise:NSInvalidArgumentException format:@"Invalid URL: %@", address];
}
NSString *scheme = hostURL.scheme;
if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
[NSException raise:NSInvalidArgumentException format:@"URL scheme %@ isn't supported.", scheme];
}
// If the user didn't specify a port (hostURL.port is nil), provide a default one.
NSNumber *port = hostURL.port ?: [scheme isEqualToString:@"https"] ? @443 : @80;
address = [@[hostURL.host, port] componentsJoinedByString:@":"];
// Look up the GRPCHost in the cache. // Look up the GRPCHost in the cache.
static NSMutableDictionary *hostCache; static NSMutableDictionary *hostCache;
@ -84,19 +74,15 @@
@synchronized(hostCache) { @synchronized(hostCache) {
GRPCHost *cachedHost = hostCache[address]; GRPCHost *cachedHost = hostCache[address];
if (cachedHost) { if (cachedHost) {
// We could verify here that the cached host uses the same protocol that we're expecting. But
// creating non-SSL channels by adding "http://" to the address is going away (to make the use
// of insecure channels less subtle), so it's not worth it now.
return cachedHost; return cachedHost;
} }
if ((self = [super init])) { if ((self = [super init])) {
_address = address; _address = address;
_secure = [scheme isEqualToString:@"https"]; _secure = YES;
hostCache[address] = self; hostCache[address] = self;
}
return self;
} }
return self;
} }
- (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue {
@ -131,4 +117,7 @@
return _hostNameOverride ?: _address; return _hostNameOverride ?: _address;
} }
// TODO(jcanizales): Don't let set |secure| to |NO| if |pathToCertificates| or |hostNameOverride|
// have been set. Don't let set either of the latter if |secure| has been set to |NO|.
@end @end

@ -35,6 +35,7 @@
#import <XCTest/XCTest.h> #import <XCTest/XCTest.h>
#import <GRPCClient/GRPCCall.h> #import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCCall+Tests.h>
#import <ProtoRPC/ProtoMethod.h> #import <ProtoRPC/ProtoMethod.h>
#import <RemoteTest/Messages.pbobjc.h> #import <RemoteTest/Messages.pbobjc.h>
#import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriteable.h>
@ -43,8 +44,7 @@
// These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall) // These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall)
// rather than a generated proto library on top of it. // rather than a generated proto library on top of it.
// grpc-test.sandbox.google.com static NSString * const kHostAddress = @"localhost:5050";
static NSString * const kHostAddress = @"http://localhost:5050";
static NSString * const kPackage = @"grpc.testing"; static NSString * const kPackage = @"grpc.testing";
static NSString * const kService = @"TestService"; static NSString * const kService = @"TestService";
@ -58,6 +58,9 @@ static ProtoMethod *kUnaryCallMethod;
@implementation GRPCClientTests @implementation GRPCClientTests
- (void)setUp { - (void)setUp {
// Register test server as non-SSL.
[GRPCCall useInsecureConnectionsForHost:kHostAddress];
// This method isn't implemented by the remote server. // This method isn't implemented by the remote server.
kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService service:kService

@ -37,7 +37,7 @@
// https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md // https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md
@interface InteropTests : XCTestCase @interface InteropTests : XCTestCase
// Returns @"http://localhost:5050". // Returns @"localhost:5050".
// Override in a subclass to perform the same tests against a different address. // Override in a subclass to perform the same tests against a different address.
// For interop tests, use @"grpc-test.sandbox.google.com". // For interop tests, use @"grpc-test.sandbox.google.com".
+ (NSString *)host; + (NSString *)host;

@ -35,6 +35,7 @@
#include <grpc/status.h> #include <grpc/status.h>
#import <GRPCClient/GRPCCall+Tests.h>
#import <ProtoRPC/ProtoRPC.h> #import <ProtoRPC/ProtoRPC.h>
#import <RemoteTest/Empty.pbobjc.h> #import <RemoteTest/Empty.pbobjc.h>
#import <RemoteTest/Messages.pbobjc.h> #import <RemoteTest/Messages.pbobjc.h>
@ -75,15 +76,22 @@
} }
@end @end
#pragma mark Tests
static NSString * const kLocalCleartextHost = @"localhost:5050";
@implementation InteropTests { @implementation InteropTests {
RMTTestService *_service; RMTTestService *_service;
} }
+ (NSString *)host { + (NSString *)host {
return @"http://localhost:5050"; return kLocalCleartextHost;
} }
- (void)setUp { - (void)setUp {
// Register test server as non-SSL.
[GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost];
_service = [[RMTTestService alloc] initWithHost:self.class.host]; _service = [[RMTTestService alloc] initWithHost:self.class.host];
} }

Loading…
Cancel
Save