Skip to content

Commit

Permalink
print parameter value if and only if provided via CLI arg or config (#…
Browse files Browse the repository at this point in the history
…464)

Follow up to #463
As per Zoom discussion, BMX will always print parameter value & source
if and only if it's provided via CLI args or config file.

I also made it colourful for legibility. The line seems too long and
crowded without these colours.
![image](https://github.com/user-attachments/assets/27461fa6-2b9a-48a1-946e-5db92d244235)

The colours don't work if stdout is redirected, which is typical when
using `bmx print`. I know why this is happening. Will try to fix in a
separate PR.

https://desire2learn.atlassian.net/browse/VUL-423
  • Loading branch information
cfbao authored Jul 24, 2024
1 parent 55ae7ba commit 351876b
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 20 deletions.
11 changes: 11 additions & 0 deletions src/D2L.Bmx/AwsCredsCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ AwsCredentials Credentials
internal class AwsCredsCreator(
IAwsClient awsClient,
IConsolePrompter consolePrompter,
IConsoleWriter consoleWriter,
IAwsCredentialCache awsCredentialCache,
BmxConfig config
) {
Expand All @@ -30,12 +31,22 @@ bool cache
);
}

var accountSource = ParameterSource.CliArg;
if( string.IsNullOrEmpty( account ) && !string.IsNullOrEmpty( config.Account ) ) {
account = config.Account;
accountSource = ParameterSource.Config;
}
if( !string.IsNullOrEmpty( account ) && !nonInteractive ) {
consoleWriter.WriteParameter( ParameterDescriptions.Account, account, accountSource );
}

var roleSource = ParameterSource.CliArg;
if( string.IsNullOrEmpty( role ) && !string.IsNullOrEmpty( config.Role ) ) {
role = config.Role;
roleSource = ParameterSource.Config;
}
if( !string.IsNullOrEmpty( role ) && !nonInteractive ) {
consoleWriter.WriteParameter( ParameterDescriptions.Role, role, roleSource );
}

if( duration is null or 0 ) {
Expand Down
6 changes: 2 additions & 4 deletions src/D2L.Bmx/ConsolePrompter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal interface IConsolePrompter {
string PromptOrg( bool allowEmptyInput );
string PromptProfile();
string PromptUser( bool allowEmptyInput );
string PromptPassword( string user, string org );
string PromptPassword();
int? PromptDuration();
string PromptAccount( string[] accounts );
string PromptRole( string[] roles );
Expand Down Expand Up @@ -63,9 +63,7 @@ string IConsolePrompter.PromptUser( bool allowEmptyInput ) {
return user;
}

string IConsolePrompter.PromptPassword( string user, string org ) {
Console.Error.WriteLine( $"{ParameterDescriptions.Org}: {org}" );
Console.Error.WriteLine( $"{ParameterDescriptions.User}: {user}" );
string IConsolePrompter.PromptPassword() {
return GetMaskedInput( $"{ParameterDescriptions.Password}: " );
}

Expand Down
17 changes: 17 additions & 0 deletions src/D2L.Bmx/ConsoleWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace D2L.Bmx;

internal interface IConsoleWriter {
void WriteParameter( string description, string value, ParameterSource source );
}

internal class ConsoleWriter : IConsoleWriter {
void IConsoleWriter.WriteParameter( string description, string value, ParameterSource source ) {
Console.ResetColor();
Console.Error.Write( $"{description}: " );
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Error.Write( value );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( $" (from {source})" );
Console.ResetColor();
}
}
31 changes: 20 additions & 11 deletions src/D2L.Bmx/OktaAuthenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal class OktaAuthenticator(
IOktaApi oktaApi,
IOktaSessionStorage sessionStorage,
IConsolePrompter consolePrompter,
IConsoleWriter consoleWriter,
BmxConfig config
) {
public async Task<AuthenticatedOktaApi> AuthenticateAsync(
Expand All @@ -21,24 +22,32 @@ public async Task<AuthenticatedOktaApi> AuthenticateAsync(
bool nonInteractive,
bool ignoreCache
) {
var orgSource = ParameterSource.CliArg;
if( string.IsNullOrEmpty( org ) && !string.IsNullOrEmpty( config.Org ) ) {
org = config.Org;
orgSource = ParameterSource.Config;
}
if( string.IsNullOrEmpty( org ) ) {
if( !string.IsNullOrEmpty( config.Org ) ) {
org = config.Org;
} else if( !nonInteractive ) {
org = consolePrompter.PromptOrg( allowEmptyInput: false );
} else {
if( nonInteractive ) {
throw new BmxException( "Org value was not provided" );
}
org = consolePrompter.PromptOrg( allowEmptyInput: false );
} else if( !nonInteractive ) {
consoleWriter.WriteParameter( ParameterDescriptions.Org, org, orgSource );
}

var userSource = ParameterSource.CliArg;
if( string.IsNullOrEmpty( user ) && !string.IsNullOrEmpty( config.User ) ) {
user = config.User;
userSource = ParameterSource.Config;
}
if( string.IsNullOrEmpty( user ) ) {
if( !string.IsNullOrEmpty( config.User ) ) {
user = config.User;
} else if( !nonInteractive ) {
user = consolePrompter.PromptUser( allowEmptyInput: false );
} else {
if( nonInteractive ) {
throw new BmxException( "User value was not provided" );
}
user = consolePrompter.PromptUser( allowEmptyInput: false );
} else if( !nonInteractive ) {
consoleWriter.WriteParameter( ParameterDescriptions.User, user, userSource );
}

oktaApi.SetOrganization( org );
Expand All @@ -50,7 +59,7 @@ bool ignoreCache
throw new BmxException( "Okta authentication failed. Please run `bmx login` first." );
}

string password = consolePrompter.PromptPassword( user, org );
string password = consolePrompter.PromptPassword();

var authnResponse = await oktaApi.AuthenticateAsync( user, password );

Expand Down
2 changes: 1 addition & 1 deletion src/D2L.Bmx/ParameterDescriptions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace D2L.Bmx;

internal static class ParameterDescriptions {
public const string Org = "Okta org short name or domain name";
public const string Org = "Okta org or domain name";
public const string User = "Okta username";
public const string Password = "Okta password";
public const string Account = "AWS account name";
Expand Down
14 changes: 14 additions & 0 deletions src/D2L.Bmx/ParameterSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace D2L.Bmx;

internal record ParameterSource {
public string Description { get; init; }

private ParameterSource( string description ) {
Description = description;
}

public static ParameterSource CliArg => new( "command line argument" );
public static ParameterSource Config => new( "config file" );

public override string ToString() => Description;
}
8 changes: 8 additions & 0 deletions src/D2L.Bmx/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
new OktaApi(),
new OktaSessionStorage(),
new ConsolePrompter(),
new ConsoleWriter(),
config
) );
return handler.HandleAsync(
Expand Down Expand Up @@ -121,16 +122,19 @@

printCommand.SetHandler( ( InvocationContext context ) => {
var consolePrompter = new ConsolePrompter();
var consoleWriter = new ConsoleWriter();
var config = new BmxConfigProvider( new FileIniDataParser() ).GetConfiguration();
var handler = new PrintHandler(
new OktaAuthenticator(
new OktaApi(),
new OktaSessionStorage(),
consolePrompter,
consoleWriter,
config ),
new AwsCredsCreator(
new AwsClient( new AmazonSecurityTokenServiceClient( new AnonymousAWSCredentials() ) ),
consolePrompter,
consoleWriter,
new AwsCredsCache(),
config )
);
Expand Down Expand Up @@ -172,19 +176,23 @@

writeCommand.SetHandler( ( InvocationContext context ) => {
var consolePrompter = new ConsolePrompter();
var consoleWriter = new ConsoleWriter();
var config = new BmxConfigProvider( new FileIniDataParser() ).GetConfiguration();
var handler = new WriteHandler(
new OktaAuthenticator(
new OktaApi(),
new OktaSessionStorage(),
consolePrompter,
consoleWriter,
config ),
new AwsCredsCreator(
new AwsClient( new AmazonSecurityTokenServiceClient( new AnonymousAWSCredentials() ) ),
consolePrompter,
consoleWriter,
new AwsCredsCache(),
config ),
consolePrompter,
consoleWriter,
config,
new FileIniDataParser()
);
Expand Down
15 changes: 11 additions & 4 deletions src/D2L.Bmx/WriteHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal class WriteHandler(
OktaAuthenticator oktaAuth,
AwsCredsCreator awsCredsCreator,
IConsolePrompter consolePrompter,
IConsoleWriter consoleWriter,
BmxConfig config,
FileIniDataParser parser
) {
Expand Down Expand Up @@ -45,12 +46,18 @@ bool useCredentialProcess
cache: cacheAwsCredentials
);

var profileSource = ParameterSource.CliArg;
if( string.IsNullOrEmpty( profile ) && !string.IsNullOrEmpty( config.Profile ) ) {
profile = config.Profile;
profileSource = ParameterSource.Config;
}
if( string.IsNullOrEmpty( profile ) ) {
if( !string.IsNullOrEmpty( config.Profile ) ) {
profile = config.Profile;
} else {
profile = consolePrompter.PromptProfile();
if( nonInteractive ) {
throw new BmxException( "Profile value was not provided" );
}
profile = consolePrompter.PromptProfile();
} else if( !nonInteractive ) {
consoleWriter.WriteParameter( ParameterDescriptions.Profile, profile, profileSource );
}

if( !string.IsNullOrEmpty( output ) && !Path.IsPathRooted( output ) ) {
Expand Down

0 comments on commit 351876b

Please sign in to comment.