Schließen Sie das Lesen und Schreiben von GCP an Secret Manager mit Google-Unterbefehlen ab

Thema

GCP hat Secret Manager. Diejenigen, die Kubernetes kennen, denken vielleicht: "Ist es so etwas wie Geheimnisse?" Da die Geheimnisse von k8s Base64-codiert sind, kann es nicht in ein öffentliches GitHub-Repository hochgeladen werden (z. B. als Name für die Verwaltung der Originaldaten), aber Secret Manager wird verschlüsselt (wenn Sie den Schlüssel nicht kennen). Genau geheim.

Siehe unten für andere Dinge wie Uri. https://cloud.google.com/blog/ja/products/identity-security/introducing-google-clouds-secret-manager

Wie im obigen Referenzartikel erwähnt, können nicht nur Secret Manager, sondern auch GCP-Dienste mithilfe von Cloud SDK vorbereitet werden. Sie können Ressourcen auf GCP einfach bedienen, indem Sie einfach auf klicken. Wie in diesem Thema ist es nicht erforderlich, einen Wrapper programmgesteuert zu schreiben. Dieses Mal habe ich einfach die Funktion zum Betreiben von Secret Manager als Betreff zum Schreiben eines geeigneten Befehlszeilentools unter Verwendung der Google-Bibliothek Unterbefehle umbrochen.

Angenommener Leser

Annahme

--Go Entwicklungsumgebung wurde lokal erstellt.

Entwicklungsumgebung

OS - Linux(Ubuntu)

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"

#Backend

#Language --Golang

$ go version
go version go1.15.2 linux/amd64

IDE - Goland

GoLand 2020.2.3
Build #GO-202.7319.61, built on September 16, 2020

Alle Quellen diesmal

https://github.com/sky0621/gcp-toolbox/tree/v0.1.0/secret-manager

Individuelle Quelle

Ich dachte, ich würde einen Kommentar schreiben, aber es sind fast alle Versprechen bei der Verwendung der Unterbefehle von Google und die Versprechen bei der Verwendung des Secret Manager SDK (dh die Informationen auf jeder Website). Keine Erklärung.

main.go

Als Funktion werden nur der Befehl " create "zum Erstellen eines Geheimnisses und der Befehl" list" zum Anzeigen einer Liste der erstellten Geheimnisse vorbereitet.

package main

import (
	"context"
	"flag"
	"os"

	"github.com/google/subcommands"
)

func main() {
	os.Exit(int(execMain()))
}

func execMain() subcommands.ExitStatus {
	subcommands.Register(subcommands.HelpCommand(), "")
	subcommands.Register(newCreateCmd(), "create")
	subcommands.Register(newListCmd(), "list")
	flag.Parse()
	return subcommands.Execute(context.Background())
}

create.go

package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"

	"github.com/google/subcommands"
)

type createCmd struct {
	projectID, key, value, path string
}

func newCreateCmd() *createCmd {
	return &createCmd{}
}

func (*createCmd) Name() string {
	return "create"
}

func (*createCmd) Synopsis() string {
	return "create secret"
}

func (*createCmd) Usage() string {
	return `usage: create secret`
}

func (cmd *createCmd) SetFlags(f *flag.FlagSet) {
	f.StringVar(&cmd.projectID, "p", "", "project id")
	f.StringVar(&cmd.key, "k", "", "key")
	f.StringVar(&cmd.value, "v", "", "value")
	f.StringVar(&cmd.path, "f", "", "file path")
}

func (cmd *createCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	if cmd.projectID == "" || cmd.key == "" || (cmd.value == "" && cmd.path == "") {
		log.Println("need -p [gcp project id] -k [secret key] -v [secret value] or -f [secret file path]")
		return subcommands.ExitFailure
	}

	var client *secretmanager.Client
	{
		var err error
		client, err = secretmanager.NewClient(ctx)
		if err != nil {
			log.Fatalf("failed to setup client: %v", err)
		}
	}

	// Create the request to create the secret.
	createSecretReq := &secretmanagerpb.CreateSecretRequest{
		Parent:   fmt.Sprintf("projects/%s", cmd.projectID),
		SecretId: cmd.key,
		Secret: &secretmanagerpb.Secret{
			Replication: &secretmanagerpb.Replication{
				Replication: &secretmanagerpb.Replication_Automatic_{
					Automatic: &secretmanagerpb.Replication_Automatic{},
				},
			},
		},
	}

	var secret *secretmanagerpb.Secret
	{
		var err error
		secret, err = client.CreateSecret(ctx, createSecretReq)
		if err != nil {
			log.Fatalf("failed to create secret: %v", err)
		}
	}

	// Declare the payload to storage.
	var payload []byte
	if cmd.value != "" {
		payload = []byte(cmd.value)
	}
	if cmd.path != "" {
		ba, err := ioutil.ReadFile(cmd.path)
		if err != nil {
			log.Fatalf("failed to read secret file: %+v", err)
		}
		payload = ba
	}
	if payload == nil {
		log.Fatal("payload is nil")
	}

	// Build the request.
	addSecretVersionReq := &secretmanagerpb.AddSecretVersionRequest{
		Parent: secret.Name,
		Payload: &secretmanagerpb.SecretPayload{
			Data: payload,
		},
	}

	var accessRequest *secretmanagerpb.AccessSecretVersionRequest
	{
		// Call the API.
		version, err := client.AddSecretVersion(ctx, addSecretVersionReq)
		if err != nil {
			log.Fatalf("failed to add secret version: %v", err)
		}

		// Build the request.
		accessRequest = &secretmanagerpb.AccessSecretVersionRequest{
			Name: version.Name,
		}
	}

	// Call the API.
	result, err := client.AccessSecretVersion(ctx, accessRequest)
	if err != nil {
		log.Fatalf("failed to access secret version: %v", err)
	}

	// Print the secret payload.
	//
	// WARNING: Do not print the secret in a production environment - this
	// snippet is showing how to access the secret material.
	log.Printf("Plaintext: %s", result.Payload.Data)

	return subcommands.ExitSuccess
}

list.go

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"strings"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"google.golang.org/api/iterator"
	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"

	"github.com/google/subcommands"
)

type listCmd struct {
	projectID string
}

func newListCmd() *listCmd {
	return &listCmd{}
}

func (*listCmd) Name() string {
	return "list"
}

func (*listCmd) Synopsis() string {
	return "list secrets"
}

func (*listCmd) Usage() string {
	return `usage: list secrets`
}

func (cmd *listCmd) SetFlags(f *flag.FlagSet) {
	f.StringVar(&cmd.projectID, "p", "", "project id")
}

func (cmd *listCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	if cmd.projectID == "" {
		log.Println("need -p [gcp project id]")
		return subcommands.ExitFailure
	}

	client, err := secretmanager.NewClient(ctx)
	if err != nil {
		log.Printf("failed to create secretmanager client: %v", err)
		return subcommands.ExitFailure
	}

	// Build the request.
	req := &secretmanagerpb.ListSecretsRequest{
		Parent: fmt.Sprintf("projects/%s", cmd.projectID),
	}

	// Call the API.
	it := client.ListSecrets(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			break
		}

		if err != nil {
			log.Printf("failed to list secret versions: %v", err)
			return subcommands.ExitFailure
		}

		names := strings.Split(resp.Name, "/")
		reqName := fmt.Sprintf("projects/%s/secrets/%s/versions/%s", names[1], names[3], "latest")

		// Build the request.
		req := &secretmanagerpb.AccessSecretVersionRequest{
			Name: reqName,
		}

		// Call the API.
		result, err := client.AccessSecretVersion(ctx, req)
		if err != nil {
			log.Printf("failed to access secret version: %v", err)
			return subcommands.ExitFailure
		}

		log.Printf("Found secret %s ... got value: %s\n", resp.Name, string(result.Payload.Data))
	}
	return subcommands.ExitSuccess
}

Trainieren

Geheimnis hinzufügen

$ go run ./*.go create -p XXXXXXXX -k rdb-host -v localhost
2020/10/11 23:03:33 Plaintext: localhost
$ go run ./*.go create -p XXXXXXXX -k rdb-port -v 12345
2020/10/11 23:04:05 Plaintext: 12345
$ go run ./*.go create -p XXXXXXXX -k rdb-user -v user1
2020/10/11 23:04:24 Plaintext: user1
$ go run ./*.go create -p XXXXXXXX -k rdb-pass -v pass1234
2020/10/11 23:04:47 Plaintext: pass1234

Mit Blick auf den GCP-Konsolenmanager sieht es so aus. screenshot-console.cloud.google.com-2020.10.11-23_05_07.png

Geheime Liste anzeigen

$ go run ./*.go list -p fs-work-21
2020/10/11 23:09:34 Found secret projects/999999999999/secrets/rdb-host ... got value: localhost
2020/10/11 23:09:35 Found secret projects/999999999999/secrets/rdb-pass ... got value: pass1234
2020/10/11 23:09:35 Found secret projects/999999999999/secrets/rdb-port ... got value: 12345
2020/10/11 23:09:35 Found secret projects/999999999999/secrets/rdb-user ... got value: user1

Zusammenfassung

Wofür werden beispielsweise die vom Secret Manager verwalteten geheimen Informationen verwendet? Ich denke, es gibt verschiedene Verwendungszwecke, aber in meinem Fall ist es an der Zeit, ein DB-Kennwort oder etwas an den Dienst zu übergeben, der über Umgebungsvariablen in Cloud Run veröffentlicht wird. Legen Sie in der Build-Shell das vom Secret Manager mit dem Befehl gcloud erhaltene DB-Kennwort fest. Spezifische Methode Ja, wir sehen uns später.

Recommended Posts

Schließen Sie das Lesen und Schreiben von GCP an Secret Manager mit Google-Unterbefehlen ab
Beispiel für das Lesen und Schreiben von CSV mit Python
Lesen und Schreiben von NetCDF mit Python
Lesen und Schreiben von CSV mit Python
Lesen und Schreiben von JSON-Dateien mit Python
Skript zum Twittern mit Vielfachen von 3 und Zahlen mit 3 !!
Lesen und Schreiben passt Dateien mit Python (Memo)
Laden Sie Dateien mit Django-Speicher in Google Cloud Storages hoch und löschen Sie sie
Lesen und Schreiben von CSV-Dateien
Reagieren und Kolben zu GCP
Speichern Sie das Ergebnis des Crawls mit Scrapy im Google Data Store
Korrespondenzanalyse von Sätzen mit COTOHA API und Speichern in Datei
Versuchen Sie, Google Map und Geography Map mit Python anzuzeigen
Die stärkste Möglichkeit, MeCab und CaboCha mit Google Colab zu verwenden
Verbesserung der Wiederverwendbarkeit und Wartbarkeit von mit Luigi erstellten Workflows