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  }