Skip to content

Commit

Permalink
add support for multiple aws sessions (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
Isan-Rivkin authored Mar 18, 2023
1 parent 3baf38f commit fb5b87f
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 223 deletions.
224 changes: 121 additions & 103 deletions cmd/acm.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
)

var (
acmMultiAWSProfile *[]string
awsRegion string
filterQuery string
acmFilterDomains *bool
Expand All @@ -55,139 +56,156 @@ var acmCmd = &cobra.Command{
- Certificate ID
surf acm -q some-acm-id --filter-id
- Multiple AWS Profiles/Regions
surf acm -q my-comain.com --aws-session profile1,region1 --aws-session profile2,region2
`,
Run: func(cmd *cobra.Command, args []string) {
tui := buildTUI()
auth, err := awsu.NewSessionInput(awsProfile, awsRegion)

sessionInputs, err := resolveAWSSessions(acmMultiAWSProfile, awsProfile, awsRegion)
if err != nil {
log.Fatalf("failed creating session in AWS %s", err.Error())
log.WithError(err).Fatalf("failed building input for AWS session")
}

acmClient, err := awsu.NewACM(auth)
auths, err := awsu.NewSessionInputMatrix(sessionInputs)

if err != nil {
log.Fatalf("failed creating ACM client %s", err.Error())
log.WithError(err).Fatalf("failed creating session in AWS")
}
for _, auth := range auths {
// auth, err := awsu.NewSessionInput(awsProfile, awsRegion)

api := awsu.NewAcmClient(acmClient)
parallel := 30
m := search.NewDefaultRegexMatcher()
if err != nil {
log.Fatalf("failed creating session in AWS %s", err.Error())
}

tui.GetLoader().Start("searching acm", "", "green")
acmClient, err := awsu.NewACM(auth)

result, err := api.ListAndFilter(parallel, true, func(c *acm.CertificateDetail) bool {
if *acmFilterAllOptions {
*acmFilterAttachedResources = true
*acmFilterDomains = true
*acmFilterID = true
if err != nil {
log.Fatalf("failed creating ACM client %s", err.Error())
}

if *acmFilterDomains {
domains := aws.StringValueSlice(c.SubjectAlternativeNames)
for _, d := range domains {
if isMatch, _ := m.IsMatch(filterQuery, d); isMatch {
return true
api := awsu.NewAcmClient(acmClient)
parallel := 30
m := search.NewDefaultRegexMatcher()

tui.GetLoader().Start("searching acm", "", "green")

result, err := api.ListAndFilter(parallel, true, func(c *acm.CertificateDetail) bool {
if *acmFilterAllOptions {
*acmFilterAttachedResources = true
*acmFilterDomains = true
*acmFilterID = true
}

if *acmFilterDomains {
domains := aws.StringValueSlice(c.SubjectAlternativeNames)
for _, d := range domains {
if isMatch, _ := m.IsMatch(filterQuery, d); isMatch {
return true
}
}
}
}
if *acmFilterAttachedResources {
usedBy := aws.StringValueSlice(c.InUseBy)
for _, arn := range usedBy {
if isMatch, _ := m.IsMatch(filterQuery, arn); isMatch {
return true
if *acmFilterAttachedResources {
usedBy := aws.StringValueSlice(c.InUseBy)
for _, arn := range usedBy {
if isMatch, _ := m.IsMatch(filterQuery, arn); isMatch {
return true
}
}
}
}
if *acmFilterID {
if isMatch, _ := m.IsMatch(filterQuery, aws.StringValue(c.CertificateArn)); isMatch {
return true
if *acmFilterID {
if isMatch, _ := m.IsMatch(filterQuery, aws.StringValue(c.CertificateArn)); isMatch {
return true
}
}
}
return false
})
return false
})

tui.GetLoader().Stop()
tui.GetLoader().Stop()

if err != nil {
log.WithError(err).Fatal("failed listing acm certificates")
}
if err != nil {
log.WithError(err).Fatal("failed listing acm certificates")
}

certs := result.Certificates
sort.SliceStable(certs, func(i, j int) bool {
c1 := certs[i]
c2 := certs[j]

c1Create := aws.TimeValue(c1.CreatedAt)
c2Create := aws.TimeValue(c2.CreatedAt)

return c2Create.After(c1Create)

})

for _, c := range result.Certificates {

arn := aws.StringValue(c.CertificateArn)
splitted := strings.Split(arn, "/")
id := splitted[len(splitted)-1]
url := awsu.GenerateACMWebURL(auth.EffectiveRegion, id)
status := aws.StringValue(c.Status)
domain := aws.StringValue(c.DomainName)
inUseBy := aws.StringValueSlice(c.InUseBy)
created := aws.TimeValue(c.CreatedAt)
notAfter := aws.TimeValue(c.NotAfter)

// date expiration

expireDays := time.Until(notAfter).Hours() / 24
// status pretty output consolidation
validationMethodsMapper := map[string]bool{}
validationStatusMapper := map[string]bool{}
validationMethods := ""
validationStatus := ""
if c.DomainValidationOptions != nil {
for _, o := range c.DomainValidationOptions {
m := aws.StringValue(o.ValidationMethod)
validationMethodsMapper[m] = true

s := aws.StringValue(o.ValidationStatus)
validationStatusMapper[s] = true
certs := result.Certificates
sort.SliceStable(certs, func(i, j int) bool {
c1 := certs[i]
c2 := certs[j]

c1Create := aws.TimeValue(c1.CreatedAt)
c2Create := aws.TimeValue(c2.CreatedAt)

return c2Create.After(c1Create)

})

for _, c := range result.Certificates {

arn := aws.StringValue(c.CertificateArn)
splitted := strings.Split(arn, "/")
id := splitted[len(splitted)-1]
url := awsu.GenerateACMWebURL(auth.EffectiveRegion, id)
status := aws.StringValue(c.Status)
domain := aws.StringValue(c.DomainName)
inUseBy := aws.StringValueSlice(c.InUseBy)
created := aws.TimeValue(c.CreatedAt)
notAfter := aws.TimeValue(c.NotAfter)

// date expiration

expireDays := time.Until(notAfter).Hours() / 24
// status pretty output consolidation
validationMethodsMapper := map[string]bool{}
validationStatusMapper := map[string]bool{}
validationMethods := ""
validationStatus := ""
if c.DomainValidationOptions != nil {
for _, o := range c.DomainValidationOptions {
m := aws.StringValue(o.ValidationMethod)
validationMethodsMapper[m] = true

s := aws.StringValue(o.ValidationStatus)
validationStatusMapper[s] = true
}
}
}

if len(validationStatusMapper) > 1 {
validationStatus = "Partial"
} else {
for s := range validationStatusMapper {
validationStatus = s
if len(validationStatusMapper) > 1 {
validationStatus = "Partial"
} else {
for s := range validationStatusMapper {
validationStatus = s
}
}
}

for m := range validationMethodsMapper {
validationMethods += m + " |"
}
for m := range validationMethodsMapper {
validationMethods += m + " |"
}

labelsOrder := []string{"Domain", "URL", "Status"}
labelsOrder := []string{"Domain", "URL", "Status"}

certInfo := map[string]string{
"Domain": domain,
"URL": url,
"Status": status,
}
certInfo := map[string]string{
"Domain": domain,
"URL": url,
"Status": status,
}

if getLogLevelFromVerbosity() >= log.DebugLevel {
labelsOrder = append(labelsOrder, []string{"Created", "Expire In", "Validation"}...)
certInfo["Created"] = created.String()
certInfo["Expire In"] = fmt.Sprintf("%d", int(expireDays))
certInfo["Validation"] = fmt.Sprintf("%s [%s]", validationMethods, validationStatus)
for i, arn := range inUseBy {
useByLabel := fmt.Sprintf("Used By %d", i)
certInfo[useByLabel] = arn
labelsOrder = append(labelsOrder, useByLabel)
if getLogLevelFromVerbosity() >= log.DebugLevel {
labelsOrder = append(labelsOrder, []string{"Created", "Expire In", "Validation"}...)
certInfo["Created"] = created.String()
certInfo["Expire In"] = fmt.Sprintf("%d", int(expireDays))
certInfo["Validation"] = fmt.Sprintf("%s [%s]", validationMethods, validationStatus)
for i, arn := range inUseBy {
useByLabel := fmt.Sprintf("Used By %d", i)
certInfo[useByLabel] = arn
labelsOrder = append(labelsOrder, useByLabel)
}
}
}

tui.GetTable().PrintInfoBox(certInfo, labelsOrder, false)
tui.GetTable().PrintInfoBox(certInfo, labelsOrder, false)
}
}
},
}
Expand All @@ -198,7 +216,7 @@ func init() {
acmCmd.PersistentFlags().StringVarP(&awsProfile, "profile", "p", getDefaultProfileEnvVar(), "~/.aws/credentials chosen account")
acmCmd.PersistentFlags().StringVarP(&awsRegion, "region", "r", "", "~/.aws/config default region if empty")
acmCmd.PersistentFlags().StringVarP(&filterQuery, "query", "q", "", "filter query regex supported")

acmMultiAWSProfile = acmCmd.PersistentFlags().StringArray("aws-session", []string{}, "search in multiple aws profiles & regions (comma separated: --aws-session default,us-east-1 --aws-session dev-account,us-west-2) - overrides --profile and --region")
acmFilterDomains = acmCmd.PersistentFlags().Bool("filter-domains", true, "compare query input against all subject names i.e domains")
acmFilterID = acmCmd.PersistentFlags().Bool("filter-id", false, "compare query input against all acm arn's")
acmFilterAttachedResources = acmCmd.PersistentFlags().Bool("filter-used-by", false, "compare query input against arn's using the acm certificate i.e load balancer")
Expand Down
Loading

0 comments on commit fb5b87f

Please sign in to comment.