Skip to content

Commit 87fa1ae

Browse files
mortenljtronghn
andcommitted
feat: Add migrator outgoing IP to authorized networks
Co-authored-by: Trong Nguyen <[email protected]>
1 parent 4909942 commit 87fa1ae

File tree

6 files changed

+76
-39
lines changed

6 files changed

+76
-39
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,3 @@ It is recommended to set the following environment variables:
135135
|------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
136136
| `DEVELOPMENT_MODE_SKIP_BACKUP=true` | Skip creating backups. These take long to create, and if developing, the backup is probably not needed. |
137137
| `DEVELOPMENT_MODE_UNSAFE_PASSWORD=true` | During setup/promotion, the password for the `postgres` user is changed. This setting makes the password always be `testpassword`. |
138-
| `DEVELOPMENT_MODE_ADD_AUTH_NETWORK=true` | Parts of setup/promotion requires connecting to the instances. This settings adds the outgoing IP of the machine running setup/promote to authorized networks on the instance. |

cmd/cleanup/main.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,32 @@ func main() {
8181
os.Exit(9)
8282
}
8383

84+
mgr.Logger.Info("deleting authorized networks")
85+
err = instance.CleanupAuthNetworks(ctx, target, mgr)
86+
if err != nil {
87+
mgr.Logger.Error("failed to cleanup authorized networks", "error", err)
88+
os.Exit(10)
89+
}
90+
8491
mgr.Logger.Info("deleting SQL SSL Certificates used during migration")
8592
err = mgr.SqlSslCertClient.DeleteCollection(ctx, v1.ListOptions{
8693
LabelSelector: "migrator.nais.io/cleanup=" + cfg.ApplicationName,
8794
})
8895
if err != nil {
8996
mgr.Logger.Error("failed to delete SQL SSL Certificates", "error", err)
90-
os.Exit(10)
97+
os.Exit(11)
9198
}
9299

93100
helperName, err := common_main.HelperName(cfg.ApplicationName)
94101
if err != nil {
95102
mgr.Logger.Error("failed to get helper name", "error", err)
96-
os.Exit(11)
103+
os.Exit(12)
97104
}
98105

99106
mgr.Logger.Info("deleting Network Policy used during migration")
100107
err = mgr.K8sClient.NetworkingV1().NetworkPolicies(cfg.Namespace).Delete(ctx, helperName, v1.DeleteOptions{})
101108
if err != nil {
102109
mgr.Logger.Error("failed to delete Network Policy", "error", err)
103-
os.Exit(12)
110+
os.Exit(13)
104111
}
105112
}

hack/env

-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ TARGET_INSTANCE_NAME=db-tester-name-${NUM}
88

99
DEVELOPMENT_MODE_SKIP_BACKUP=true
1010
DEVELOPMENT_MODE_UNSAFE_PASSWORD=true
11-
DEVELOPMENT_MODE_ADD_AUTH_NETWORK=true

internal/pkg/config/develop.go

-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,4 @@ type Development struct {
66

77
// Sets an unsafe, pre-defined password for postgres user
88
UnsafePassword bool `env:"UNSAFE_PASSWORD"`
9-
10-
// Looks up outgoing PrimaryIp via https://api.ipify.org and adds it to the authorized networks for instances
11-
AddAuthNetwork bool `env:"ADD_AUTH_NETWORK"`
129
}

internal/pkg/instance/instance.go

+52-21
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ import (
1919
"net/http"
2020
"os"
2121
"os/user"
22+
"strings"
2223
"time"
2324
)
2425

2526
const (
26-
dummyAppImage = "europe-north1-docker.pkg.dev/nais-io/nais/images/kafka-debug:latest"
27-
updateRetries = 3
27+
dummyAppImage = "europe-north1-docker.pkg.dev/nais-io/nais/images/kafka-debug:latest"
28+
updateRetries = 3
29+
migrationAuthNetworkPrefix = "migrator:"
2830
)
2931

3032
func CreateInstance(ctx context.Context, cfg *config.Config, source *resolved.Instance, gcpProject *resolved.GcpProject, databaseName string, mgr *common_main.Manager) (*resolved.Instance, error) {
@@ -145,14 +147,11 @@ func prepareSourceInstanceWithRetries(ctx context.Context, cfg *config.Config, s
145147
}
146148
sourceSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = appendAuthNetIfNotExists(sourceSqlInstance, authNetwork)
147149

148-
if cfg.Development.AddAuthNetwork {
149-
authNetwork, err = createDevelopmentAuthNetwork()
150-
if err != nil {
151-
return err
152-
}
153-
154-
sourceSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = appendAuthNetIfNotExists(sourceSqlInstance, authNetwork)
150+
authNetwork, err = createMigratorAuthNetwork()
151+
if err != nil {
152+
return err
155153
}
154+
sourceSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = appendAuthNetIfNotExists(sourceSqlInstance, authNetwork)
156155

157156
setFlag(sourceSqlInstance, "cloudsql.enable_pglogical")
158157
setFlag(sourceSqlInstance, "cloudsql.logical_decoding")
@@ -208,16 +207,14 @@ func prepareTargetInstanceWithRetries(ctx context.Context, cfg *config.Config, t
208207

209208
targetSqlInstance.Spec.Settings.BackupConfiguration.Enabled = ptr.To(false)
210209

211-
if cfg.Development.AddAuthNetwork {
212-
var authNetwork v1beta1.InstanceAuthorizedNetworks
213-
authNetwork, err = createDevelopmentAuthNetwork()
214-
if err != nil {
215-
return err
216-
}
217-
218-
targetSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = appendAuthNetIfNotExists(targetSqlInstance, authNetwork)
210+
var authNetwork v1beta1.InstanceAuthorizedNetworks
211+
authNetwork, err = createMigratorAuthNetwork()
212+
if err != nil {
213+
return err
219214
}
220215

216+
targetSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = appendAuthNetIfNotExists(targetSqlInstance, authNetwork)
217+
221218
_, err = mgr.SqlInstanceClient.Update(ctx, targetSqlInstance)
222219
if err != nil {
223220
if k8s_errors.IsConflict(err) && retries > 0 {
@@ -296,12 +293,35 @@ func DeleteInstance(ctx context.Context, instanceName string, gcpProject *resolv
296293
return nil
297294
}
298295

299-
func createDevelopmentAuthNetwork() (v1beta1.InstanceAuthorizedNetworks, error) {
296+
func CleanupAuthNetworks(ctx context.Context, target *resolved.Instance, mgr *common_main.Manager) error {
297+
return cleanupAuthNetworksWithRetries(ctx, target, mgr, updateRetries)
298+
}
299+
300+
func cleanupAuthNetworksWithRetries(ctx context.Context, target *resolved.Instance, mgr *common_main.Manager, retries int) error {
301+
targetSqlInstance, err := mgr.SqlInstanceClient.Get(ctx, target.Name)
302+
if err != nil {
303+
return fmt.Errorf("failed to get target instance: %w", err)
304+
}
305+
306+
targetSqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks = removeMigrationAuthNetwork(targetSqlInstance)
307+
308+
_, err = mgr.SqlInstanceClient.Update(ctx, targetSqlInstance)
309+
if err != nil {
310+
if k8s_errors.IsConflict(err) && retries > 0 {
311+
mgr.Logger.Info("retrying update of target instance", "remaining_retries", retries)
312+
return cleanupAuthNetworksWithRetries(ctx, target, mgr, retries-1)
313+
}
314+
return err
315+
}
316+
return nil
317+
}
318+
319+
func createMigratorAuthNetwork() (v1beta1.InstanceAuthorizedNetworks, error) {
300320
outgoingIp, err := getOutgoingIp()
301321
if err != nil {
302322
return v1beta1.InstanceAuthorizedNetworks{}, err
303323
}
304-
name, err := getDeveloperName()
324+
name, err := getNetworkName()
305325
if err != nil {
306326
return v1beta1.InstanceAuthorizedNetworks{}, err
307327
}
@@ -313,7 +333,7 @@ func createDevelopmentAuthNetwork() (v1beta1.InstanceAuthorizedNetworks, error)
313333
return authNetwork, nil
314334
}
315335

316-
func getDeveloperName() (string, error) {
336+
func getNetworkName() (string, error) {
317337
u, err := user.Current()
318338
if err != nil {
319339
return "", err
@@ -324,7 +344,7 @@ func getDeveloperName() (string, error) {
324344
return "", err
325345
}
326346

327-
return fmt.Sprintf("%s@%s", u.Username, h), nil
347+
return fmt.Sprintf("%s%s@%s", migrationAuthNetworkPrefix, u.Username, h), nil
328348
}
329349

330350
func getOutgoingIp() (string, error) {
@@ -345,6 +365,17 @@ func getOutgoingIp() (string, error) {
345365
return string(data), nil
346366
}
347367

368+
func removeMigrationAuthNetwork(sqlInstance *v1beta1.SQLInstance) []v1beta1.InstanceAuthorizedNetworks {
369+
newAuthNetworks := make([]v1beta1.InstanceAuthorizedNetworks, 0)
370+
for _, network := range sqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks {
371+
if strings.HasPrefix(migrationAuthNetworkPrefix, *network.Name) {
372+
continue
373+
}
374+
newAuthNetworks = append(newAuthNetworks, network)
375+
}
376+
return newAuthNetworks
377+
}
378+
348379
func appendAuthNetIfNotExists(sqlInstance *v1beta1.SQLInstance, authNetwork v1beta1.InstanceAuthorizedNetworks) []v1beta1.InstanceAuthorizedNetworks {
349380
for _, network := range sqlInstance.Spec.Settings.IpConfiguration.AuthorizedNetworks {
350381
if network.Value == authNetwork.Value {

internal/pkg/netpol/netpol.go

+14-10
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,12 @@ func CreateNetworkPolicy(ctx context.Context, cfg *config.Config, source *resolv
4242
},
4343
Egress: []v1.NetworkPolicyEgressRule{{
4444
To: []v1.NetworkPolicyPeer{
45-
{
46-
IPBlock: &v1.IPBlock{
47-
CIDR: fmt.Sprintf("%s/32", source.PrimaryIp),
48-
},
49-
},
50-
{
51-
IPBlock: &v1.IPBlock{
52-
CIDR: fmt.Sprintf("%s/32", target.PrimaryIp),
53-
},
54-
},
45+
makeIPBlock(source.PrimaryIp),
46+
makeIPBlock(target.PrimaryIp),
47+
// IPs for api.ipify.org
48+
makeIPBlock("104.26.13.205"),
49+
makeIPBlock("104.26.12.205"),
50+
makeIPBlock("172.67.74.152"),
5551
},
5652
}},
5753
PolicyTypes: []v1.PolicyType{v1.PolicyTypeEgress},
@@ -72,3 +68,11 @@ func CreateNetworkPolicy(ctx context.Context, cfg *config.Config, source *resolv
7268

7369
return nil
7470
}
71+
72+
func makeIPBlock(ip string) v1.NetworkPolicyPeer {
73+
return v1.NetworkPolicyPeer{
74+
IPBlock: &v1.IPBlock{
75+
CIDR: fmt.Sprintf("%s/32", ip),
76+
},
77+
}
78+
}

0 commit comments

Comments
 (0)