Skip to content

Commit 3b4a1b9

Browse files
authored
Merge pull request #21 from mjcheetham/mac-adal-logs
Fix the MSAuthHelper on macOS to trace ADAL logs and return correct exit codes
2 parents 11a5d7c + a2b685e commit 3b4a1b9

File tree

11 files changed

+149
-28
lines changed

11 files changed

+149
-28
lines changed

common/src/Microsoft.Git.CredentialManager/Authentication/MicrosoftAuthentication.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,14 @@ public async Task<IDictionary<string, string>> InvokeHelperAsync(IDictionary<str
5353
{
5454
RedirectStandardInput = true,
5555
RedirectStandardOutput = true,
56-
RedirectStandardError = true,
56+
RedirectStandardError = false, // Do not redirect stderr as tracing might be enabled
5757
UseShellExecute = false
5858
};
5959

60+
// We flush the trace writers here so that the we don't stomp over the
61+
// authentication helper's messages.
62+
_context.Trace.Flush();
63+
6064
var process = Process.Start(procStartInfo);
6165

6266
await process.StandardInput.WriteDictionaryAsync(input);

common/src/Microsoft.Git.CredentialManager/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public static class EnvironmentVariables
1313
{
1414
public const string GcmTrace = "GCM_TRACE";
1515
public const string GcmTraceSecrets = "GCM_TRACE_SECRETS";
16+
public const string GcmTraceMsAuth = "GCM_TRACE_MSAUTH";
1617
public const string GcmDebug = "GCM_DEBUG";
1718
public const string GitTerminalPrompts = "GIT_TERMINAL_PROMPT";
1819
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
platform :osx, '10.11'
22

33
target 'Microsoft.Authentication.Helper' do
4-
pod 'ADAL', '~> 2.5.1'
4+
pod 'ADAL', '~> 4.0.0'
55
end
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
PODS:
2-
- ADAL (2.5.4):
3-
- ADAL/app-lib (= 2.5.4)
4-
- ADAL/app-lib (2.5.4):
2+
- ADAL (4.0.0):
3+
- ADAL/app-lib (= 4.0.0)
4+
- ADAL/app-lib (4.0.0):
55
- ADAL/tokencacheheader
66

77
DEPENDENCIES:
8-
- ADAL (~> 2.5.1)
8+
- ADAL (~> 4.0.0)
99

1010
SPEC REPOS:
1111
https://github.com/cocoapods/specs.git:
1212
- ADAL
1313

1414
SPEC CHECKSUMS:
15-
ADAL: e7e5aca957d6c67e88cdd68ee3d0c4c4af55e874
15+
ADAL: 2f09070fb5a7095172e34409459eca3f3f1d0d23
1616

17-
PODFILE CHECKSUM: aea86594216c71aff5d22f8947aea9501e7ece3f
17+
PODFILE CHECKSUM: f7b3f5867bd6bb83186e92dedf7b8183795ffc5d
1818

1919
COCOAPODS: 1.5.3

macos/Microsoft.Authentication.Helper/Source/Core/AHAppDelegate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ typedef void(^AHAppWorkBlock) (void);
1414

1515
@property (retain, nonatomic) NSApplication* application;
1616
@property (retain, nonatomic) NSError* error;
17-
@property (assign, nonatomic) BOOL userLoggingAllowed;
1817

1918
-(id)initWithBlock:(AHAppWorkBlock)block logger:(AHLogger*)logger;
2019

macos/Microsoft.Authentication.Helper/Source/Core/AHAppDelegate.m

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ -(void)run
2626
[application setDelegate:self];
2727
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
2828

29-
if ([self userLoggingAllowed])
30-
{
31-
[_logger log:@"Creating application context for authentication prompt"];
32-
}
29+
AHLOG(_logger, @"Creating application context for authentication prompt");
3330

3431
[NSApp run];
3532
}

macos/Microsoft.Authentication.Helper/Source/Core/AHGenerateAccessToken.m

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,15 @@ + (NSString*) generateAccessTokenWithAuthority:(NSString*)authority
2828

2929
ADAuthenticationCallback completionBlock = ^(ADAuthenticationResult *result)
3030
{
31-
accessToken = result.accessToken;
31+
if (result.status == AD_SUCCEEDED)
32+
{
33+
accessToken = result.accessToken;
34+
}
35+
else // AD_FAILED or AD_USER_CANCELLED
36+
{
37+
[appDelegate setError:result.error];
38+
}
39+
3240
[appDelegate stop];
3341
};
3442

macos/Microsoft.Authentication.Helper/Source/Core/AHLogger.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#import <Foundation/Foundation.h>
55
#import "AHLogWriter.h"
66

7+
#define AHLOG(LOGGER,MSG) [LOGGER log:(MSG) fileName:@__FILE__ lineNum:__LINE__]
8+
#define AHLOG_SECRET(LOGGER,MSG,SECRET) [LOGGER log:(MSG) secretMsg:(SECRET) fileName:@__FILE__ lineNum:__LINE__]
9+
710
NS_ASSUME_NONNULL_BEGIN
811

912
@interface AHLogger : NSObject
@@ -12,9 +15,17 @@ NS_ASSUME_NONNULL_BEGIN
1215
NSDateFormatter *dateFormatter;
1316
}
1417

18+
@property BOOL enableSecretTracing;
19+
1520
- (instancetype) init;
1621
- (void) addWriter:(NSObject<AHLogWriter> *) writer;
17-
- (void) log:(NSString*)message;
22+
- (void) log:(NSString*)message
23+
fileName:(NSString*)fileName
24+
lineNum:(int)lineNum;
25+
- (void) log:(NSString*)message
26+
secretMsg:(NSString*)secretMsg
27+
fileName:(NSString*)fileName
28+
lineNum:(int)lineNum;
1829

1930
@end
2031

macos/Microsoft.Authentication.Helper/Source/Core/AHLogger.m

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ -(instancetype)init
1212
{
1313
self->writers = [[NSMutableArray<AHLogWriter> alloc] init];
1414
self->dateFormatter = [[NSDateFormatter alloc] init];
15-
[self->dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss:SSS"];
15+
16+
// Configure the date formatter based on the POSIX locale as "HH" can still return
17+
// a 12-hour style time if the user's locale has disabled the 24-hour style.
18+
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
19+
[self->dateFormatter setLocale:enUSPOSIXLocale];
20+
[self->dateFormatter setDateFormat:@"HH:mm:ss:SSSSSS"];
1621
}
1722

1823
return self;
@@ -24,9 +29,21 @@ - (void) addWriter:(NSObject<AHLogWriter> *) writer
2429
}
2530

2631
-(void)log:(NSString*)message
32+
fileName:(NSString*)fileName
33+
lineNum:(int)lineNum
2734
{
28-
NSString* logMessage = [NSString stringWithFormat:@"%@: %@\n",
29-
[dateFormatter stringFromDate:[NSDate date]],
35+
// To be consistent with Git and GCM's main trace output format we want the source (file:line)
36+
// column to be 23 characters wide, truncating the start with "..." if required.
37+
NSString* source = [[NSString alloc] initWithFormat:@"%@:%d", fileName, lineNum];
38+
if ([source length] > 23)
39+
{
40+
NSInteger extra = [source length] - 23 + 3;
41+
source = [[NSString alloc] initWithFormat:@"...%@", [source substringFromIndex:extra]];
42+
}
43+
44+
NSString* logMessage = [NSString stringWithFormat:@"%@ %23s trace: %@\n",
45+
[dateFormatter stringFromDate:[NSDate date]],
46+
[source UTF8String],
3047
message];
3148

3249
for (NSObject<AHLogWriter> *writer in self->writers)
@@ -35,4 +52,26 @@ -(void)log:(NSString*)message
3552
}
3653
}
3754

55+
-(void)log:(NSString*)message
56+
secretMsg:(NSString*)secretMsg
57+
fileName:(NSString*)fileName
58+
lineNum:(int)lineNum;
59+
{
60+
NSString* combinedMessage;
61+
if ([self enableSecretTracing])
62+
{
63+
combinedMessage = [[NSString alloc] initWithFormat:@"%@ PII: %@",
64+
message, secretMsg];
65+
}
66+
else
67+
{
68+
combinedMessage = [[NSString alloc] initWithFormat:@"%@ PII: ********",
69+
message];
70+
}
71+
72+
[self log:combinedMessage
73+
fileName:fileName
74+
lineNum:lineNum];
75+
}
76+
3877
@end

macos/Microsoft.Authentication.Helper/Source/main.m

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#import "AHLogger.h"
88
#import "AHFileLogWriter.h"
99
#import "AHStdErrorLogWriter.h"
10+
#import <ADAL/ADAL.h>
1011

1112
BOOL isTruthy(NSString* value) {
1213
if (value == nil) {
@@ -24,28 +25,77 @@ BOOL isLocalFilePath(NSString *path) {
2425
}
2526

2627
int main(int argc, const char * argv[]) {
28+
2729
@autoreleasepool {
30+
int exitCode;
2831
NSError* error;
2932

3033
AHLogger *logger = [[AHLogger alloc] init];
3134

32-
NSString* traceEnvar = [[[NSProcessInfo processInfo] environment] objectForKey:@"GCM_TRACE"];
35+
// Configure the application logger based on the common GCM tracing environment variables
36+
NSString* traceEnvar = [[[NSProcessInfo processInfo] environment] objectForKey:@"GCM_TRACE"];
37+
NSString* traceSecretsEnvar = [[[NSProcessInfo processInfo] environment] objectForKey:@"GCM_TRACE_SECRETS"];
38+
NSString* traceMsAuthEnvar = [[[NSProcessInfo processInfo] environment] objectForKey:@"GCM_TRACE_MSAUTH"];
3339

40+
// Enable tracing
3441
if (isTruthy(traceEnvar)) {
3542
[logger addWriter:[[AHStdErrorLogWriter alloc] init]];
3643
}
3744
else if (isLocalFilePath(traceEnvar)) {
3845
[logger addWriter:[[AHFileLogWriter alloc] initWithPath:traceEnvar]];
3946
}
4047

41-
[logger log:@"Running Microsoft Authentication helper for macOS"];
48+
// Enable tracing of secret/sensitive information
49+
if (isTruthy(traceSecretsEnvar)) {
50+
[logger setEnableSecretTracing:YES];
51+
52+
// Also enable PII logging in ADAL
53+
[ADLogger setPiiEnabled:YES];
54+
}
55+
56+
// Always disable ADAL from logging to NSLog which prints to stderror directly
57+
[ADLogger setNSLogging:NO];
58+
59+
// Register a callback in ADAL for our logger if GCM_TRACE_MSAUTH is enabled
60+
if (isTruthy(traceMsAuthEnvar))
61+
{
62+
// We try and capture everything we can as this can help with diagnosing
63+
// the most complicated authentication problems.
64+
[ADLogger setLevel:ADAL_LOG_LEVEL_VERBOSE];
65+
66+
[ADLogger setLoggerCallback:^(ADAL_LOG_LEVEL logLevel, NSString *message, BOOL containsPii) {
67+
68+
NSString* logLevelName;
69+
switch (logLevel) {
70+
case ADAL_LOG_LEVEL_ERROR:
71+
logLevelName = @"Error";
72+
break;
73+
case ADAL_LOG_LEVEL_WARN:
74+
logLevelName = @"Warning";
75+
break;
76+
case ADAL_LOG_LEVEL_INFO:
77+
logLevelName = @"Info";
78+
break;
79+
case ADAL_LOG_LEVEL_VERBOSE:
80+
logLevelName = @"Verbose";
81+
break;
82+
default:
83+
logLevelName = @"Unknown";
84+
break;
85+
}
86+
87+
[logger log:[NSString stringWithFormat:@"[ADAL] [%@] %@", logLevelName, message] fileName:@"ADAL" lineNum:0];
88+
}];
89+
}
90+
91+
AHLOG(logger, @"Running Microsoft Authentication helper for macOS");
4292

4393
NSMutableDictionary<NSString *, NSString *> *configs = [NSMutableDictionary dictionaryFromFileHandle:[NSFileHandle fileHandleWithStandardInput]];
4494

4595
// Extract expected parameters from input
46-
NSString* authority = [configs objectForKey:@"authority"];
47-
NSString* clientId = [configs objectForKey:@"clientId"];
48-
NSString* resource = [configs objectForKey:@"resource"];
96+
NSString* authority = [configs objectForKey:@"authority"];
97+
NSString* clientId = [configs objectForKey:@"clientId"];
98+
NSString* resource = [configs objectForKey:@"resource"];
4999
NSString* redirectUri = [configs objectForKey:@"redirectUri"];
50100

51101
NSString *accessToken = [AHGenerateAccessToken generateAccessTokenWithAuthority:authority
@@ -55,9 +105,20 @@ int main(int argc, const char * argv[]) {
55105
error:&error
56106
logger:logger];
57107

58-
NSString* output = [NSString stringWithFormat:@"accessToken=%@\n", accessToken];
108+
NSString* output;
109+
110+
if (error == nil && accessToken != nil)
111+
{
112+
output = [NSString stringWithFormat:@"accessToken=%@\n", accessToken];
113+
exitCode = 0;
114+
}
115+
else
116+
{
117+
output = [NSString stringWithFormat:@"error=%@\n", [error description]];
118+
exitCode = -1;
119+
}
120+
59121
[output writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:&error];
122+
return exitCode;
60123
}
61-
62-
return 0;
63124
}

0 commit comments

Comments
 (0)