gcp/dam_import/main.go (120 lines of code) (raw):

// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Binary dam_reset to reset the storage of a DAM package main import ( "context" "flag" "strings" "google.golang.org/grpc/codes" /* copybara-comment */ "google.golang.org/grpc/status" /* copybara-comment */ "github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/dam" /* copybara-comment: dam */ "github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/dsstore" /* copybara-comment: dsstore */ "github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/saw" /* copybara-comment: saw */ "github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/storage" /* copybara-comment: storage */ glog "github.com/golang/glog" /* copybara-comment */ ) func main() { pre := flag.String("account_prefix", "", "when a wipe is requested, accounts matching this prefix override will be removed") path := flag.String("path", "deploy/config", "specifies the relative or absolute path to the config file root") wipe := flag.String("wipe", "", "specify 'unsafe_wipe_in_non_production' to remove all data for the service from the storage layer first (DO NOT USE IN PRODUCTION)") flag.Parse() args := flag.Args() if len(args) != 3 { glog.Exitf("Usage: dam_import -wipe=... -path=<config_root> -account_prefix=<service_account_prefix_to_delete> <project> <environment> <import_type>") } project := args[0] env := args[1] importType := args[2] envPrefix := "" service := "dam" if len(env) > 0 { envPrefix = "-" + env service += envPrefix } accountPrefix := "ic" + envPrefix + "-dot-" if *pre != "" { accountPrefix = *pre } ctx := context.Background() store := dsstore.NewStore(context.Background(), project, service, *path) wh := saw.MustNew(ctx, store) vars := map[string]string{ "${YOUR_PROJECT_ID}": project, "${YOUR_ENVIRONMENT}": envPrefix, } if *wipe != "" { if *wipe != "unsafe_wipe_in_non_production" { glog.Exitf("attempted wipe failed: only works if specific safety value set. See -h for help.") } glog.Infof("WIPE STORAGE FOR SERVICE %q...", service) if _, err := store.Wipe(ctx, storage.AllRealms, 0, 0); err != nil { glog.Exitf("error wiping storage for service %q: %v", service, err) } glog.Infof("Wipe complete") } importConfig := false importSecrets := false importPermission := false switch importType { case "all": importConfig = true importSecrets = true importPermission = true case "config": importConfig = true case "security": importSecrets = true case "permission": importPermission = true default: glog.Exitf("unknown importing config type: %s", importType) } if err := dam.ImportConfig(store, service, wh, vars, importConfig, importSecrets, importPermission); err != nil { glog.Exitf("error importing files: %v", err) } if *wipe != "" { cleanupServiceAccounts(ctx, accountPrefix, project, store) } glog.Infof("SUCCESS resetting DAM service %q", service) } func cleanupServiceAccounts(ctx context.Context, accountPrefix, project string, store *dsstore.Store) { wh := saw.MustNew(ctx, store) var ( removed, skipped, errors int emails []string ) maxErrors := 20 aborted := "" ctx, cancel := context.WithCancel(ctx) defer cancel() accounts, err := wh.GetServiceAccounts(ctx, project) if err != nil { glog.Errorf("fetching service accounts from project %q failed: %v", project, err) return } for a := range accounts { // DAM adds service account DisplayName of the form: subject|service_full_path // so pull out the service_full_path and match on the accountPrefix provided. parts := strings.SplitN(a.DisplayName, "|", 2) if len(parts) < 2 || !strings.HasPrefix(parts[1], accountPrefix) { skipped++ continue } emails = append(emails, a.ID) } for _, email := range emails { err := wh.RemoveServiceAccount(ctx, project, email) switch status.Code(err) { case codes.OK: removed++ case codes.NotFound: glog.Infof("deleting service account %q on project %q: acccount does not exist.", email, project) default: errors++ if errors >= maxErrors { aborted = "+ (aborted early)" break } if errors < 3 { glog.Errorf("deleting service account %q on project %q failed: %v", email, project, err) } } } glog.Infof("status of removing service accounts: project %q, prefix %q, matched %d, removed %d, skipped %d, errors %d%s", project, accountPrefix, len(emails), removed, skipped, errors, aborted) }