func fetchEphemeralCert()

in internal/cloudsql/refresh.go [174:249]


func fetchEphemeralCert(
	ctx context.Context,
	client *sqladmin.Service,
	inst instance.ConnName,
	key *rsa.PrivateKey,
	tp auth.TokenProvider,
) (c tls.Certificate, err error) {
	var end trace.EndSpanFunc
	ctx, end = trace.StartSpan(ctx, "cloud.google.com/go/cloudsqlconn/internal.FetchEphemeralCert")
	defer func() { end(err) }()
	clientPubKey, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
	if err != nil {
		return tls.Certificate{}, err
	}

	req := sqladmin.GenerateEphemeralCertRequest{
		PublicKey: string(pem.EncodeToMemory(&pem.Block{Bytes: clientPubKey, Type: "RSA PUBLIC KEY"})),
	}
	var tok *auth.Token
	if tp != nil {
		var tokErr error
		tok, tokErr = tp.Token(ctx)
		if tokErr != nil {
			return tls.Certificate{}, errtype.NewRefreshError(
				"failed to retrieve Oauth2 token",
				inst.String(),
				tokErr,
			)
		}
		req.AccessToken = tok.Value
	}
	resp, err := retry50x(ctx, func(ctx2 context.Context) (*sqladmin.GenerateEphemeralCertResponse, error) {
		return client.Connect.GenerateEphemeralCert(
			inst.Project(), inst.Name(), &req,
		).Context(ctx2).Do()
	}, exponentialBackoff)
	if err != nil {
		return tls.Certificate{}, errtype.NewRefreshError(
			"create ephemeral cert failed",
			inst.String(),
			err,
		)
	}

	// parse the client cert
	b, _ := pem.Decode([]byte(resp.EphemeralCert.Cert))
	if b == nil {
		return tls.Certificate{}, errtype.NewRefreshError(
			"failed to decode valid PEM cert",
			inst.String(),
			nil,
		)
	}
	clientCert, err := x509.ParseCertificate(b.Bytes)
	if err != nil {
		return tls.Certificate{}, errtype.NewRefreshError(
			fmt.Sprintf("failed to parse as X.509 certificate: %v", err),
			inst.String(),
			nil,
		)
	}
	if tp != nil {
		// Adjust the certificate's expiration to be the earliest of
		// the token's expiration or the certificate's expiration.
		if tok.Expiry.Before(clientCert.NotAfter) {
			clientCert.NotAfter = tok.Expiry
		}
	}

	c = tls.Certificate{
		Certificate: [][]byte{clientCert.Raw},
		PrivateKey:  key,
		Leaf:        clientCert,
	}
	return c, nil
}