Skip to content

Commit

Permalink
New List RDS Profile & Get AWS Credentials command (#9)
Browse files Browse the repository at this point in the history
New List RDS Profile & Get AWS Credentials command
  • Loading branch information
vgmello authored Nov 7, 2023
1 parent e24a005 commit c2840e0
Show file tree
Hide file tree
Showing 18 changed files with 193 additions and 70 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ jobs:
- name: Create Release
uses: softprops/action-gh-release@v1
with:
prerelease: contains(github.ref, 'beta') || contains(github.ref, 'alpha')
files: win-output/aws-cred-mgr-win-x64.zip
generate_release_notes: true
files: win-output/aws-cred-mgr-win-x64.zip
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ Contributions are welcome! Please fork the repository and submit a pull request

This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the [Code of Conduct](CODE_OF_CONDUCT.md).

## Credits and Acknowledgements

`aws-cred-mgr` makes use of several open-source libraries. We extend our gratitude to the developers and contributors of these libraries:

- **[AngleSharp](https://github.com/AngleSharp/AngleSharp)**: A .NET library for parsing, manipulating, and rendering HTML and CSS documents.
- **[AWSSDK](https://github.com/aws/aws-sdk-net)**: The official AWS SDK for the .NET Framework.
- **[Serilog.Extensions.Logging](https://github.com/serilog/serilog-extensions-logging)**: An extension to `Microsoft.Extensions.Logging` that integrates Serilog.
- **[Serilog.Sinks.File](https://github.com/serilog/serilog-sinks-file)**: A Serilog sink that writes log events to text files.
- **[Spectre.Console](https://github.com/spectreconsole/spectre.console)**: A library for building command line interfaces.
- **[YamlDotNet](https://github.com/aaubry/YamlDotNet)**: A .NET library for YAML serialization and deserialization.

Each of these libraries may be licensed differently, so we recommend you to review their licenses if you plan to use `aws-cred-mgr` in your own projects.

## License

This project is licensed under the terms of the MIT license.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

using System.Globalization;
using Amazon;
using Ellosoft.AwsCredentialsManager.Services.Okta;

namespace Ellosoft.AwsCredentialsManager.Commands.AWS;

Expand All @@ -13,11 +12,6 @@ public class AwsSettings : CommonSettings
[TypeConverter(typeof(AwsRegionConverter))]
public RegionEndpoint? Region { get; set; }

[CommandOption("--okta-profile")]
[Description("Local Okta profile name (Useful if you need to authenticate in multiple Okta domains)")]
[DefaultValue("default")]
public virtual string OktaUserProfile { get; set; } = OktaConstants.DefaultProfileName;

/// <summary>
/// Get AWS region endpoint
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Ellosoft.AwsCredentialsManager.Commands.AWS;
using Ellosoft.AwsCredentialsManager.Services.AWS;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Interactive;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Models;
using Ellosoft.AwsCredentialsManager.Services.Okta;
using Ellosoft.AwsCredentialsManager.Services.Okta.Interactive;
using Ellosoft.AwsCredentialsManager.Services.Okta.Models.HttpModels;
Expand Down Expand Up @@ -34,6 +35,11 @@ public class Settings : AwsSettings
[CommandOption("--okta-app-url")]
[Description("URL of the AWS application in Okta")]
public string? OktaAppUrl { get; set; }

[CommandOption("--okta-profile")]
[Description("Local Okta profile name (Useful if you need to authenticate in multiple Okta domains)")]
[DefaultValue("default")]
public string OktaUserProfile { get; set; } = OktaConfiguration.DefaultProfileName;
}

private readonly CredentialsManager _credentialsManager;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) 2023 Ellosoft Limited. All rights reserved.

using System.Diagnostics.CodeAnalysis;
using Ellosoft.AwsCredentialsManager.Commands.AWS;
using Ellosoft.AwsCredentialsManager.Services.AWS;
using Ellosoft.AwsCredentialsManager.Services.AWS.Interactive;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Interactive;

namespace Ellosoft.AwsCredentialsManager.Commands.Credentials;

Expand All @@ -11,15 +11,42 @@ namespace Ellosoft.AwsCredentialsManager.Commands.Credentials;
[Examples(
"get prod",
"get prod --aws-profile default")]
public class GetCredentials : Command<AwsSettings>
public class GetCredentials : AsyncCommand<GetCredentials.Settings>
{
public override int Execute([NotNull] CommandContext context, [NotNull] AwsSettings settings)
public class Settings : AwsSettings
{
var credentialsService = new AwsCredentialsService();
[CommandArgument(0, "[CREDENTIAL_NAME]")]
[Description("AWS credential profile name (use [italic blue]cred new[/] to create a new profile)")]
public string? Credential { get; set; }

#pragma warning disable S1481 // Unused local variables should be removed
var x = credentialsService.GetCredentialsFromStore("default");
#pragma warning restore S1481 // Unused local variables should be removed
[CommandOption("-p|--aws-profile")]
[Description("AWS profile to use (profile used in AWS CLI)")]
[DefaultValue("default")]
public string? AwsProfile { get; set; }
}

private readonly CredentialsManager _credentialsManager;
private readonly AwsOktaSessionManager _sessionManager;

public GetCredentials(
CredentialsManager credentialsManager,
AwsOktaSessionManager sessionManager
)
{
_credentialsManager = credentialsManager;
_sessionManager = sessionManager;
}

public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
{
var credential = settings.Credential ?? _credentialsManager.GetCredential();

var awsCredentials = await _sessionManager.CreateOrResumeSessionAsync(credential);

if (awsCredentials is null)
return 1;

AnsiConsole.MarkupLine($"[green]AWS credentials stored in the '{settings.AwsProfile}' AWS profile[/]");

return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@
using System.Diagnostics.CodeAnalysis;
using Ellosoft.AwsCredentialsManager.Commands.AWS;
using Ellosoft.AwsCredentialsManager.Services.Configuration;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Models;

namespace Ellosoft.AwsCredentialsManager.Commands.Credentials;

[Name("list"), Alias("ls")]
[Description("List all saved credential profiles")]
[Description("List saved credential profiles")]
[Examples("ls")]
public class ListCredentialsProfiles : Command<AwsSettings>
public class ListCredentialsProfiles : Command<ListCredentialsProfiles.Settings>
{
public class Settings : AwsSettings
{
[CommandOption("--okta-profile")]
[Description("Local Okta profile name (Useful if you need to authenticate in multiple Okta domains)")]
[DefaultValue("default")]
public string OktaUserProfile { get; set; } = OktaConfiguration.DefaultProfileName;
}

private readonly IConfigManager _configManager;

public ListCredentialsProfiles(IConfigManager configManager) => _configManager = configManager;

public override int Execute([NotNull] CommandContext context, [NotNull] AwsSettings settings)
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings)
{
var credentials = _configManager.AppConfig.Credentials;

Expand Down
5 changes: 2 additions & 3 deletions src/Ellosoft.AwsCredentialsManager/Commands/Okta/SetupOkta.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

using Ellosoft.AwsCredentialsManager.Services.Configuration;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Models;
using Ellosoft.AwsCredentialsManager.Services.Okta;
using Ellosoft.AwsCredentialsManager.Services.Okta.Interactive;

namespace Ellosoft.AwsCredentialsManager.Commands.Okta;
Expand All @@ -18,9 +17,9 @@ public class SetupOkta : AsyncCommand<SetupOkta.Settings>
public class Settings : CommonSettings
{
[CommandArgument(0, "[PROFILE]")]
[DefaultValue(OktaConstants.DefaultProfileName)]
[DefaultValue(OktaConfiguration.DefaultProfileName)]
[Description("Local Okta profile name (Useful if you need to authenticate in multiple Okta domains)")]
public string Profile { get; set; } = OktaConstants.DefaultProfileName;
public string Profile { get; set; } = OktaConfiguration.DefaultProfileName;

[CommandOption("-d|--domain")]
[Description("Your organization Okta domain URL (e.g. https://xyz.okta.com)")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class Settings : AwsSettings
public string? Username { get; set; }

[CommandOption("--ttl")]
[Description("Password lifetime in minutes (max recommended: 15 minutes)")]
[Description("Password lifetime in minutes (max allowed: 15 minutes)")]
[DefaultValue(DatabaseConfiguration.DefaultTtlInMinutes)]
public int Ttl { get; set; }

Expand Down
71 changes: 67 additions & 4 deletions src/Ellosoft.AwsCredentialsManager/Commands/RDS/ListRdsProfiles.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
// Copyright (c) 2023 Ellosoft Limited. All rights reserved.

using System.Diagnostics.CodeAnalysis;
using Ellosoft.AwsCredentialsManager.Commands.AWS;
using Ellosoft.AwsCredentialsManager.Services.Configuration;
using Ellosoft.AwsCredentialsManager.Services.Configuration.Models;

namespace Ellosoft.AwsCredentialsManager.Commands.RDS;

[Name("list"), Alias("ls")]
[Description("List all saved AWS RDS profiles")]
[Description("List saved AWS RDS profiles")]
[Examples("ls")]
public class ListRdsProfiles : Command<AwsSettings>
public class ListRdsProfiles : Command<ListRdsProfiles.Settings>
{
public override int Execute([NotNull] CommandContext context, [NotNull] AwsSettings settings)
public class Settings : CommonSettings
{
[CommandOption("--env")]
[Description("Environment name")]
public string? Environment { get; set; }
}

private readonly IConfigManager _configManager;

public ListRdsProfiles(IConfigManager configManager) => _configManager = configManager;

public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings)
{
var environments = settings.Environment is null
? _configManager.AppConfig.Environments
: _configManager.AppConfig.Environments.Where(k => k.Key == settings.Environment);

foreach (var (envName, env) in environments)
RenderTable(envName, env);

return 0;
}

private void RenderTable(string environmentName, EnvironmentConfiguration env)
{
var table = new Table()
.Title($"[green]Environment: {environmentName}[/]")
.AddColumn("Name")
.AddColumn("Hostname")
.AddColumn("Port")
.AddColumn("Username")
.AddColumn("Region")
.AddColumn("Credential")
.AddColumn("Template")
.Expand()
.Caption("[grey62][[*]] Inherited value[/]");

foreach (var (rdsName, dbConfig) in env.Rds.OrderBy(kv => kv.Key))
{
var template = GetRdsTemplate(dbConfig.Template, _configManager.AppConfig);

table.AddRow(
rdsName,
PrintValue(dbConfig.Hostname, template?.Hostname),
PrintValue(dbConfig.Port?.ToString(), template?.Port?.ToString()),
PrintValue(dbConfig.Username, template?.Username),
PrintValue(dbConfig.Region, template?.Region),
PrintValue(dbConfig.Credential, env.Credential),
PrintValue(dbConfig.Template, null)
);
}

AnsiConsole.Write(table);
AnsiConsole.WriteLine();
}

public static DatabaseConfiguration? GetRdsTemplate(string? templateName, AppConfig appConfig)
{
if (templateName is null)
return null;

return appConfig.Templates?.Rds.TryGetValue(templateName, out var template) == true ? template : null;
}

private static string PrintValue(string? value, string? inheritedValue) =>
value ?? (inheritedValue is not null ? $"[grey62 i]{inheritedValue} *[/]" : "--");
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ public IBranchConfigurator<TBranchSettings> AddBranch<TBranch>(Action<IBranchCon
{
return AddBranch<TBranch, TBranchSettings>(branchConfigAction);
}

public IBranchConfigurator<TBranchSettings> SetDefaultCommand<TCommand>() where TCommand : class, ICommandLimiter<TBranchSettings>
{
_configurator.SetDefaultCommand<TCommand>();

return this;
}
}

public interface IBranchConfigurator<in TBranchSettings> where TBranchSettings : CommandSettings
Expand All @@ -56,4 +63,6 @@ IBranchConfigurator<TBranchSettings> AddBranch<TBranch, TDerivedSettings>(Action

IBranchConfigurator<TBranchSettings> AddBranch<TBranch>(Action<IBranchConfigurator<TBranchSettings>> branchConfigAction)
where TBranch : class;

IBranchConfigurator<TBranchSettings> SetDefaultCommand<TCommand>() where TCommand : class, ICommandLimiter<TBranchSettings>;
}
22 changes: 13 additions & 9 deletions src/Ellosoft.AwsCredentialsManager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Ellosoft.AwsCredentialsManager.Services.Okta;
using Ellosoft.AwsCredentialsManager.Services.Okta.Interactive;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Events;

var logger = LogRegistration.CreateNewLogger();

Expand Down Expand Up @@ -54,26 +55,25 @@
})
.AddBranch<CredentialsBranch>(cred =>
{
//cred.AddCommand<GetCredentials>();
cred.AddCommand<GetCredentials>();
cred.AddCommand<ListCredentialsProfiles>();
cred.AddCommand<CreateCredentialsProfile>();
})
.AddBranch<RdsBranch>(rds =>
{
rds.AddCommand<GetRdsPassword>();
//rds.AddCommand<ListRdsProfiles>();
rds.AddCommand<ListRdsProfiles>();
});

config.PropagateExceptions();
config.ValidateExamples();
});

#if DEBUG
if (Debugger.IsAttached)
{
args = "rds pwd test_db".Split(' ');
}
config.ValidateExamples();

if (Debugger.IsAttached)
args = "rds pwd test_db".Split(' ');
#endif
});

try
{
Expand All @@ -86,7 +86,11 @@
catch (Exception e)
{
logger.Error(e, "Unexpected error");
AnsiConsole.MarkupLine($"[red bold]Error: [/]{e.Message}");

if (logger.IsEnabled(LogEventLevel.Debug))
AnsiConsole.WriteException(e);
else
AnsiConsole.MarkupLine($"[red bold]Error: [/]{e.Message}");
}

return -1;
Loading

0 comments on commit c2840e0

Please sign in to comment.