github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/cloud/aws/athena/adapt.go (about) 1 package athena 2 3 import ( 4 "fmt" 5 6 "github.com/khulnasoft-lab/defsec/pkg/concurrency" 7 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 8 9 api "github.com/aws/aws-sdk-go-v2/service/athena" 10 "github.com/aws/aws-sdk-go-v2/service/athena/types" 11 "github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws" 12 "github.com/khulnasoft-lab/defsec/pkg/providers/aws/athena" 13 "github.com/khulnasoft-lab/defsec/pkg/state" 14 ) 15 16 type adapter struct { 17 *aws.RootAdapter 18 client *api.Client 19 } 20 21 func init() { 22 aws.RegisterServiceAdapter(&adapter{}) 23 } 24 25 func (a *adapter) Provider() string { 26 return "aws" 27 } 28 29 func (a *adapter) Name() string { 30 return "athena" 31 } 32 33 func (a *adapter) Adapt(root *aws.RootAdapter, state *state.State) error { 34 35 a.RootAdapter = root 36 a.client = api.NewFromConfig(root.SessionConfig()) 37 var err error 38 39 state.AWS.Athena.Workgroups, err = a.getWorkgroups() 40 if err != nil { 41 return err 42 } 43 44 state.AWS.Athena.Databases, err = a.getDatabases() 45 if err != nil { 46 return err 47 } 48 49 return nil 50 } 51 52 func (a *adapter) getWorkgroups() ([]athena.Workgroup, error) { 53 54 a.Tracker().SetServiceLabel("Discovering workgroups...") 55 56 var apiWorkgroups []types.WorkGroupSummary 57 var input api.ListWorkGroupsInput 58 for { 59 output, err := a.client.ListWorkGroups(a.Context(), &input) 60 if err != nil { 61 return nil, err 62 } 63 apiWorkgroups = append(apiWorkgroups, output.WorkGroups...) 64 a.Tracker().SetTotalResources(len(apiWorkgroups)) 65 if output.NextToken == nil { 66 break 67 } 68 input.NextToken = output.NextToken 69 } 70 71 a.Tracker().SetServiceLabel("Adapting workgroups...") 72 return concurrency.Adapt(apiWorkgroups, a.RootAdapter, a.adaptWorkgroup), nil 73 } 74 75 func (a *adapter) adaptWorkgroup(workgroup types.WorkGroupSummary) (*athena.Workgroup, error) { 76 metadata := a.CreateMetadata(fmt.Sprintf("workgroup/%s", *workgroup.Name)) 77 78 output, err := a.client.GetWorkGroup(a.Context(), &api.GetWorkGroupInput{ 79 WorkGroup: workgroup.Name, 80 }) 81 if err != nil { 82 return nil, err 83 } 84 85 var enforce bool 86 var encType string 87 if config := output.WorkGroup.Configuration; config != nil { 88 if config.EnforceWorkGroupConfiguration != nil { 89 enforce = *config.EnforceWorkGroupConfiguration 90 } 91 if resultConfig := config.ResultConfiguration; resultConfig != nil { 92 if resultConfig.EncryptionConfiguration != nil { 93 encType = string(resultConfig.EncryptionConfiguration.EncryptionOption) 94 } 95 } 96 97 } 98 99 name := defsecTypes.StringDefault("", metadata) 100 if workgroup.Name != nil { 101 name = defsecTypes.String(*workgroup.Name, metadata) 102 } 103 104 return &athena.Workgroup{ 105 Metadata: metadata, 106 Name: name, 107 Encryption: athena.EncryptionConfiguration{ 108 Metadata: metadata, 109 Type: defsecTypes.String(encType, metadata), 110 }, 111 EnforceConfiguration: defsecTypes.Bool(enforce, metadata), 112 }, nil 113 } 114 115 func (a *adapter) getDatabases() ([]athena.Database, error) { 116 117 a.Tracker().SetServiceLabel("Discovering catalogues...") 118 119 var apiCatalogues []types.DataCatalogSummary 120 var input api.ListDataCatalogsInput 121 for { 122 output, err := a.client.ListDataCatalogs(a.Context(), &input) 123 if err != nil { 124 return nil, err 125 } 126 apiCatalogues = append(apiCatalogues, output.DataCatalogsSummary...) 127 a.Tracker().SetTotalResources(len(apiCatalogues)) 128 if output.NextToken == nil { 129 break 130 } 131 input.NextToken = output.NextToken 132 } 133 134 a.Tracker().SetServiceLabel("Adapting catalogues...") 135 136 var databases []athena.Database 137 138 for _, apiCatalogue := range apiCatalogues { 139 catalogueDatabases, err := a.getDatabasesForCatalogue(apiCatalogue) 140 if err != nil { 141 return nil, err 142 } 143 databases = append(databases, catalogueDatabases...) 144 a.Tracker().IncrementResource() 145 } 146 return databases, nil 147 } 148 149 func (a *adapter) getDatabasesForCatalogue(catalog types.DataCatalogSummary) ([]athena.Database, error) { 150 151 var apiDatabases []types.Database 152 input := api.ListDatabasesInput{ 153 CatalogName: catalog.CatalogName, 154 } 155 for { 156 output, err := a.client.ListDatabases(a.Context(), &input) 157 if err != nil { 158 return nil, err 159 } 160 apiDatabases = append(apiDatabases, output.DatabaseList...) 161 if output.NextToken == nil { 162 break 163 } 164 input.NextToken = output.NextToken 165 } 166 return concurrency.Adapt(apiDatabases, a.RootAdapter, a.adaptDatabase), nil 167 } 168 169 func (a *adapter) adaptDatabase(database types.Database) (*athena.Database, error) { 170 metadata := a.CreateMetadata("database/" + *database.Name) 171 name := defsecTypes.StringDefault("", metadata) 172 if database.Name != nil { 173 name = defsecTypes.String(*database.Name, metadata) 174 } 175 176 return &athena.Database{ 177 Metadata: metadata, 178 Name: name, 179 Encryption: athena.EncryptionConfiguration{ 180 Metadata: metadata, 181 // see https://stackoverflow.com/questions/72456689/what-does-encryption-configuration-in-terraform-aws-athena-database-resource 182 Type: defsecTypes.String("", defsecTypes.NewUnmanagedMetadata()), 183 }, 184 }, nil 185 }