@@ -6,32 +6,20 @@ package logical
66
77import (
88 "context"
9- "encoding/json"
109 "fmt"
1110
1211 "github.com/aws/aws-sdk-go/aws"
13- "github.com/aws/aws-sdk-go/aws/arn"
14- "github.com/aws/aws-sdk-go/aws/awserr"
1512 "github.com/aws/aws-sdk-go/aws/session"
1613 "github.com/aws/aws-sdk-go/service/iam"
1714 "github.com/aws/aws-sdk-go/service/rds"
1815 "github.com/aws/aws-sdk-go/service/rds/rdsutils"
19- "github.com/docker/docker/api/types/mount"
2016 "github.com/pkg/errors"
2117
2218 "gitlab.com/postgres-ai/database-lab/pkg/log"
2319)
2420
2521const (
2622 sslRootCert = "/cert/ssl-combined-ca-bundle.pem"
27-
28- // AWS service names.
29- serviceIAM = "iam"
30- serviceRDSDB = "rds-db"
31-
32- // RDS policy option values.
33- rdsDocPolicyVersion = "2012-10-17"
34- rdsDBConnectAction = "rds-db:connect"
3523)
3624
3725type rdsDumper struct {
@@ -42,22 +30,9 @@ type rdsDumper struct {
4230
4331// RDSConfig describes configuration of an RDS instance.
4432type RDSConfig struct {
45- IamPolicyName string `yaml:"iamPolicyName"`
46- AWSRegion string `yaml:"awsRegion"`
47- DBInstance string `yaml:"dbInstanceIdentifier"`
48- Username string `yaml:"username"`
49- SSLRootCert string `yaml:"sslRootCert"`
50- }
51-
52- type policyDocument struct {
53- Version string `json:"Version"`
54- Statement []policyStatement `json:"Statement"`
55- }
56-
57- type policyStatement struct {
58- Effect string `json:"Effect"`
59- Action []string `json:"Action"`
60- Resource []string `json:"Resource"`
33+ AWSRegion string `yaml:"awsRegion"`
34+ DBInstance string `yaml:"dbInstanceIdentifier"`
35+ SSLRootCert string `yaml:"sslRootCert"`
6136}
6237
6338func newRDSDumper (rdsCfg * RDSConfig ) (* rdsDumper , error ) {
@@ -85,30 +60,20 @@ Set up valid environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY`)
8560
8661// GetEnvVariables returns dumper environment variables.
8762func (r * rdsDumper ) GetCmdEnvVariables () []string {
63+ cert := sslRootCert
64+
65+ if r .rdsCfg .SSLRootCert != "" {
66+ cert = r .rdsCfg .SSLRootCert
67+ }
68+
8869 execEnvs := []string {
89- "PGSSLROOTCERT=" + sslRootCert ,
70+ "PGSSLROOTCERT=" + cert ,
9071 "PGSSLMODE=verify-ca" ,
9172 }
9273
9374 return execEnvs
9475}
9576
96- // GetMounts returns dumper volume configurations for mounting.
97- func (r * rdsDumper ) GetMounts () []mount.Mount {
98- mounts := []mount.Mount {}
99-
100- if r .rdsCfg != nil && r .rdsCfg .SSLRootCert != "" {
101- // TODO (akartasov): Remove mounting after the image contains a built-in certificate.
102- mounts = append (mounts , mount.Mount {
103- Type : mount .TypeBind ,
104- Source : r .rdsCfg .SSLRootCert ,
105- Target : sslRootCert ,
106- })
107- }
108-
109- return mounts
110- }
111-
11277// SetConnectionOptions sets connection options for dumping.
11378func (r * rdsDumper ) SetConnectionOptions (ctx context.Context , c * Connection ) error {
11479 dbInstancesOutput , err := r .rdsSvc .DescribeDBInstancesWithContext (ctx , & rds.DescribeDBInstancesInput {
@@ -126,28 +91,6 @@ func (r *rdsDumper) SetConnectionOptions(ctx context.Context, c *Connection) err
12691
12792 dbInstance := dbInstancesOutput .DBInstances [0 ]
12893
129- dbARN := dbInstancesOutput .DBInstances [0 ].DBInstanceArn
130- parsedDBArn , err := arn .Parse (aws .StringValue (dbARN ))
131-
132- if err != nil {
133- return errors .Wrap (err , "failed to parse a database ARN" )
134- }
135-
136- policy , err := r .getPolicy (r .getPolicyARN (parsedDBArn ).String (), parsedDBArn , dbInstance )
137- if err != nil {
138- return errors .Wrap (err , "failed to get a policy" )
139- }
140-
141- _ , err = r .iamSvc .AttachUserPolicy (& iam.AttachUserPolicyInput {
142- PolicyArn : policy .Arn ,
143- UserName : aws .String (r .rdsCfg .Username ),
144- })
145- if err != nil {
146- return errors .Wrap (err , "failed to attach policy to a user" )
147- }
148-
149- log .Msg (fmt .Sprintf ("Policy %q has been attached to %s" , aws .StringValue (policy .Arn ), r .rdsCfg .Username ))
150-
15194 dbAuthToken , err := rdsutils .BuildAuthToken (
15295 fmt .Sprintf ("%s:%d" , aws .StringValue (dbInstance .Endpoint .Address ), int (aws .Int64Value (dbInstance .Endpoint .Port ))),
15396 r .rdsCfg .AWSRegion ,
@@ -164,67 +107,3 @@ func (r *rdsDumper) SetConnectionOptions(ctx context.Context, c *Connection) err
164107
165108 return nil
166109}
167-
168- func (r * rdsDumper ) getPolicyARN (parsedDBArn arn.ARN ) arn.ARN {
169- policyARN := arn.ARN {
170- Partition : parsedDBArn .Partition ,
171- Service : serviceIAM ,
172- AccountID : parsedDBArn .AccountID ,
173- Resource : "policy/" + r .rdsCfg .IamPolicyName ,
174- }
175-
176- return policyARN
177- }
178-
179- func (r * rdsDumper ) getPolicy (policyARN string , parsedDBArn arn.ARN , dbInstance * rds.DBInstance ) (* iam.Policy , error ) {
180- policyOutput , err := r .iamSvc .GetPolicy (& iam.GetPolicyInput {
181- PolicyArn : aws .String (policyARN ),
182- })
183- if err == nil {
184- return policyOutput .Policy , nil
185- }
186-
187- if awsErr , ok := err .(awserr.Error ); ok && awsErr .Code () != iam .ErrCodeNoSuchEntityException {
188- return nil , errors .Wrap (err , "failed to get policy" )
189- }
190-
191- policyDocumentData , err := json .Marshal (r .buildPolicyDocument (parsedDBArn , dbInstance ))
192- if err != nil {
193- return nil , errors .Wrap (err , "failed to marshal a policy document" )
194- }
195-
196- createPolicyOutput , err := r .iamSvc .CreatePolicy (& iam.CreatePolicyInput {
197- PolicyDocument : aws .String (string (policyDocumentData )),
198- PolicyName : aws .String (r .rdsCfg .IamPolicyName ),
199- })
200- if err != nil {
201- return nil , errors .Wrap (err , "failed to create a policy" )
202- }
203-
204- log .Msg (fmt .Sprintf ("Policy has been created: %v" , aws .StringValue (createPolicyOutput .Policy .Arn )))
205-
206- return createPolicyOutput .Policy , nil
207- }
208-
209- func (r * rdsDumper ) buildPolicyDocument (parsedDBArn arn.ARN , dbInstance * rds.DBInstance ) policyDocument {
210- dbPolicyARN := arn.ARN {
211- Partition : parsedDBArn .Partition ,
212- Service : serviceRDSDB ,
213- Region : parsedDBArn .Region ,
214- AccountID : parsedDBArn .AccountID ,
215- Resource : fmt .Sprintf ("dbuser:%s/*" , aws .StringValue (dbInstance .DbiResourceId )),
216- }
217-
218- policyDocument := policyDocument {
219- Version : rdsDocPolicyVersion ,
220- Statement : []policyStatement {
221- {
222- Effect : "Allow" ,
223- Action : []string {rdsDBConnectAction },
224- Resource : []string {dbPolicyARN .String ()},
225- },
226- },
227- }
228-
229- return policyDocument
230- }
0 commit comments