-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathaws.go
More file actions
257 lines (226 loc) · 7.41 KB
/
aws.go
File metadata and controls
257 lines (226 loc) · 7.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1
package resources
import (
"bytes"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io"
"strings"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/smithy-go/transport/http"
"go.mondoo.com/cnquery/v12/llx"
"go.mondoo.com/cnquery/v12/providers-sdk/v1/inventory"
"go.mondoo.com/cnquery/v12/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v12/providers/aws/connection"
"go.mondoo.com/cnquery/v12/providers/network/resources/certificates"
"go.mondoo.com/cnquery/v12/types"
"k8s.io/client-go/util/cert"
)
const (
vpcArnPattern = "arn:aws:vpc:%s:%s:id/%s"
elbv1LbArnPattern = "arn:aws:elasticloadbalancing:%s:%s:loadbalancer/classic/%s"
cloudwatchAlarmArnPattern = "arn:aws:cloudwatch:%s:%s:metricalarm/%s/%s"
ec2InstanceArnPattern = "arn:aws:ec2:%s:%s:instance/%s"
securityGroupArnPattern = "arn:aws:ec2:%s:%s:security-group/%s"
volumeArnPattern = "arn:aws:ec2:%s:%s:volume/%s"
snapshotArnPattern = "arn:aws:ec2:%s:%s:snapshot/%s"
internetGwArnPattern = "arn:aws:ec2:%s:%s:gateway/%s"
vpnConnArnPattern = "arn:aws:ec2:%s:%s:vpn-connection/%s"
networkAclArnPattern = "arn:aws:ec2:%s:%s:network-acl/%s"
imageArnPattern = "arn:aws:ec2:%s:%s:image/%s"
keypairArnPattern = "arn:aws:ec2:%s:%s:keypair/%s"
subnetArnPattern = "arn:aws:ec2:%s:%s:subnet/%s"
s3ArnPattern = "arn:aws:s3:::%s"
dynamoTableArnPattern = "arn:aws:dynamodb:%s:%s:table/%s"
limitsArn = "arn:aws:dynamodb:%s:%s"
dynamoGlobalTableArnPattern = "arn:aws:dynamodb:-:%s:globaltable/%s"
rdsInstanceArnPattern = "arn:aws:rds:%s:%s:db:%s"
apiArnPattern = "arn:aws:apigateway:%s:%s::/apis/%s"
apiStageArnPattern = "arn:aws:apigateway:%s:%s::/apis/%s/stages/%s"
)
func NewSecurityGroupArn(region, accountID, sgID string) string {
return fmt.Sprintf(securityGroupArnPattern, region, accountID, sgID)
}
func (a *mqlAws) regions() ([]any, error) {
conn := a.MqlRuntime.Connection.(*connection.AwsConnection)
res := []any{}
regions, err := conn.Regions()
for i := range regions {
res = append(res, regions[i])
}
return res, err
}
func Is400AccessDeniedError(err error) bool {
var respErr *http.ResponseError
if errors.As(err, &respErr) {
if (respErr.HTTPStatusCode() == 400 || respErr.HTTPStatusCode() == 403) && (strings.Contains(respErr.Error(), "AccessDenied") || strings.Contains(respErr.Error(), "UnauthorizedOperation") || strings.Contains(respErr.Error(), "AuthorizationError")) {
return true
}
}
return false
}
// IsMacieNotEnabledError checks if the error indicates Macie is not enabled in the region
func IsMacieNotEnabledError(err error) bool {
if err == nil {
return false
}
var respErr *http.ResponseError
if errors.As(err, &respErr) {
// Macie returns 401 status code with AccessDeniedException when not enabled
if respErr.HTTPStatusCode() == 401 && strings.Contains(respErr.Error(), "AccessDeniedException: Macie is not enabled") {
return true
}
// Also catch general access denied cases for Macie
if (respErr.HTTPStatusCode() == 400 || respErr.HTTPStatusCode() == 401 || respErr.HTTPStatusCode() == 403) &&
(strings.Contains(respErr.Error(), "AccessDeniedException") || strings.Contains(respErr.Error(), "AccessDenied")) {
return true
}
}
return false
}
func Is400InstanceNotFoundError(err error) bool {
var respErr *http.ResponseError
if errors.As(err, &respErr) {
if respErr.HTTPStatusCode() == 400 && (strings.Contains(respErr.Error(), "InvalidInstanceID.NotFound") || strings.Contains(respErr.Error(), "InvalidInstanceID.Malformed")) {
return true
}
}
return false
}
func toInterfaceMap(m map[string]string) map[string]any {
res := make(map[string]any)
for k, v := range m {
res[k] = v
}
return res
}
func toInterfaceArr(a []string) []any {
res := []any{}
for _, v := range a {
res = append(res, v)
}
return res
}
func GetRegionFromArn(arnVal string) (string, error) {
parsedArn, err := arn.Parse(arnVal)
if err != nil {
return "", err
}
return parsedArn.Region, nil
}
func CertificatesToMqlCertificates(runtime *plugin.Runtime, certs []*x509.Certificate) ([]any, error) {
res := []any{}
// to create certificate resources
for i := range certs {
cert := certs[i]
if cert == nil {
continue
}
certdata, err := certificates.EncodeCertAsPEM(cert)
if err != nil {
return nil, err
}
r, err := CreateResource(runtime, "certificate", map[string]*llx.RawData{
"pem": llx.StringData(string(certdata)),
// NOTE: if we do not set the hash here, it will generate the cache content before we can store it
// we are using the hashes for the id, therefore it is required during creation
"fingerprints": llx.MapData(certificates.Fingerprints(cert), types.String),
})
if err != nil {
return nil, err
}
c := r.(*mqlAwsAcmCertificate)
// c.Certificate = plugin.TValue[*x509.Certificate]{
// Pem: llx.StringData(cert.Pem),
// Data: cert,
// State: plugin.StateIsSet,
// } // TODO: revisit all this cert stuff. can we share resources across providers??
res = append(res, c)
}
return res, nil
}
func ParseCertsFromPEM(r io.Reader) ([]*x509.Certificate, error) {
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
certs, err := cert.ParseCertsPEM(data)
if err != nil {
return nil, err
}
return certs, nil
}
func EncodeCertAsPEM(cert *x509.Certificate) ([]byte, error) {
certBuffer := bytes.Buffer{}
if err := pem.Encode(&certBuffer, &pem.Block{Type: CertificateBlockType, Bytes: cert.Raw}); err != nil {
return nil, err
}
return certBuffer.Bytes(), nil
}
const (
// CertificateBlockType is a possible value for pem.Block.Type.
CertificateBlockType = "CERTIFICATE"
)
type assetIdentifier struct {
name string
arn string
}
func getAssetIdentifier(runtime *plugin.Runtime) *assetIdentifier {
var a *inventory.Asset
if conn, ok := runtime.Connection.(*connection.AwsConnection); ok {
a = conn.Asset()
}
if a == nil {
return nil
}
arn := ""
for _, id := range a.PlatformIds {
if strings.HasPrefix(id, "arn:aws:") {
arn = id
}
}
return &assetIdentifier{name: a.Name, arn: arn}
}
func mapStringInterfaceToStringString(m map[string]any) map[string]string {
newM := make(map[string]string)
for k, v := range m {
newM[k] = v.(string)
}
return newM
}
func remove(s []string, r string) []string {
for i, v := range s {
if v == r {
return append(s[:i], s[i+1:]...)
}
}
return s
}
// securityGroupIdHandler is a helper struct to handle security group ids and convert them to resources
// This makes it easy to extend the internal representation of a resource and fetch security groups asynchronous
type securityGroupIdHandler struct {
securityGroupArns []string
}
// setSecurityGroupArns sets the security group arns
func (sgh *securityGroupIdHandler) setSecurityGroupArns(ids []string) {
sgh.securityGroupArns = ids
}
// newSecurityGroupResources creates new security group resources based on the security group arns
func (sgh *securityGroupIdHandler) newSecurityGroupResources(runtime *plugin.Runtime) ([]any, error) {
sgs := []any{}
for i := range sgh.securityGroupArns {
sgArn := sgh.securityGroupArns[i]
mqlSg, err := NewResource(runtime, "aws.ec2.securitygroup",
map[string]*llx.RawData{
"arn": llx.StringData(sgArn),
})
if err != nil {
return nil, err
}
sgs = append(sgs, mqlSg)
}
return sgs, nil
}