Skip to content

Commit

Permalink
Merge pull request #334 from wallyworld/update-loggo-dep
Browse files Browse the repository at this point in the history
#334

Update the upstream loggo dependency to v2.

The module version is bumped to v4.

To break a circular import dependency, we also move the RpcPassThroughError from the `juju/cmd` repo to here.
The `juju/cmd` repo will be updated to use the error from here.
  • Loading branch information
jujubot authored Feb 8, 2024
2 parents 4b17505 + a9bc4d8 commit 56659c6
Show file tree
Hide file tree
Showing 96 changed files with 458 additions and 414 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PROJECT := github.com/juju/utils/v3
PROJECT := github.com/juju/utils/v4

.PHONY: check-licence check-go check

Expand Down
2 changes: 1 addition & 1 deletion arch/arch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3/arch"
"github.com/juju/utils/v4/arch"
)

type archSuite struct {
Expand Down
2 changes: 1 addition & 1 deletion attempt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

gc "gopkg.in/check.v1"

"github.com/juju/utils/v3"
"github.com/juju/utils/v4"
)

func doSomething() (int, error) { return 0, nil }
Expand Down
2 changes: 1 addition & 1 deletion bzr/bzr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3/bzr"
"github.com/juju/utils/v4/bzr"
)

func Test(t *stdtesting.T) {
Expand Down
2 changes: 1 addition & 1 deletion cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
gc "gopkg.in/check.v1"
"gopkg.in/errgo.v1"

"github.com/juju/utils/v3/cache"
"github.com/juju/utils/v4/cache"
)

type suite struct{}
Expand Down
38 changes: 18 additions & 20 deletions cert/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
package cert

import (
"crypto"
"crypto/ed25519"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha512"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -48,7 +50,6 @@ type Config struct {
IsCA bool // IsCA if we want to generate new a CA cert
Hostnames []string // Hostnames , list of hostnames for the certificate
ExtKeyUsage []x509.ExtKeyUsage // ExtKeyUsage extra flags for special usage of the cert
KeyBits int // KeyBits is used to set the lenght of the RSA key, default value 2048 bytes
Client bool // generate client certificate for certificate authentication
}

Expand All @@ -58,7 +59,7 @@ type Config struct {
func NewLeaf(cfg *Config) (certPEM, keyPEM string, err error) {
var (
caCert *x509.Certificate
caKey *rsa.PrivateKey
caKey ed25519.PrivateKey
)

if cfg.CA != nil && cfg.CAKey != nil && !cfg.IsCA {
Expand All @@ -78,19 +79,14 @@ func NewLeaf(cfg *Config) (certPEM, keyPEM string, err error) {
return "", "", errors.Errorf("CA certificate is not a valid CA")
}
var ok bool
caKey, ok = tlsCert.PrivateKey.(*rsa.PrivateKey)
caKey, ok = tlsCert.PrivateKey.(ed25519.PrivateKey)
if !ok {
return "", "", errors.Errorf("CA private key has unexpected type %T", tlsCert.PrivateKey)
}
}

// if none assign default
if cfg.KeyBits == 0 {
cfg.KeyBits = 2048
}

// generate private key
key, err := rsa.GenerateKey(rand.Reader, cfg.KeyBits)
_, key, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return "", "", errors.Errorf("cannot generate key: %v", err)
}
Expand Down Expand Up @@ -121,7 +117,7 @@ func NewLeaf(cfg *Config) (certPEM, keyPEM string, err error) {
NotBefore: now.UTC().AddDate(0, 0, -7),
Version: 2,
NotAfter: cfg.Expiry.UTC(),
SubjectKeyId: bigIntHash(key.N),
SubjectKeyId: sha512.New384().Sum(key),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement,
ExtKeyUsage: cfg.ExtKeyUsage,
}
Expand Down Expand Up @@ -161,9 +157,13 @@ func NewLeaf(cfg *Config) (certPEM, keyPEM string, err error) {
Bytes: certDER,
})

keyData, err := x509.MarshalPKCS8PrivateKey(key)
if err != nil {
return "", "", err
}
keyPEMData := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
Type: "PRIVATE KEY",
Bytes: keyData,
})
return string(certPEMData), string(keyPEMData), nil
}
Expand All @@ -185,7 +185,6 @@ func NewCA(commonName, UUID string, expiry time.Time, keyBits int) (certPEM, key
UUID: UUID,
Expiry: expiry,
IsCA: true,
KeyBits: keyBits,
})
if err != nil {
return "", "", errors.Annotatef(err, "cannot generate ca certificate")
Expand All @@ -194,13 +193,12 @@ func NewCA(commonName, UUID string, expiry time.Time, keyBits int) (certPEM, key
}

// NewClientCert generates a x509 client certificate used for https authentication sessions.
func NewClientCert(commonName, UUID string, expiry time.Time, keyBits int) (certPEM string, keyPEM string, err error) {
func NewClientCert(commonName, UUID string, expiry time.Time) (certPEM string, keyPEM string, err error) {
certPEM, keyPEM, err = NewLeaf(&Config{
CommonName: commonName,
UUID: UUID,
Expiry: expiry,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
KeyBits: keyBits,
Client: true,
})
if err != nil {
Expand Down Expand Up @@ -249,7 +247,7 @@ func newSerialNumber() (*big.Int, error) {
// this will return nil if the key is not RSA type
func getPublicKey(p interface{}) interface{} {
switch t := p.(type) {
case *rsa.PrivateKey:
case ed25519.PrivateKey:
return t.Public()
default:
return nil
Expand All @@ -275,7 +273,7 @@ func ParseCert(certPEM string) (*x509.Certificate, error) {

// ParseCertAndKey parses the given PEM-formatted X509 certificate
// and RSA private key.
func ParseCertAndKey(certPEM, keyPEM string) (*x509.Certificate, *rsa.PrivateKey, error) {
func ParseCertAndKey(certPEM, keyPEM string) (*x509.Certificate, crypto.Signer, error) {
tlsCert, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM))
if err != nil {
return nil, nil, err
Expand All @@ -286,9 +284,9 @@ func ParseCertAndKey(certPEM, keyPEM string) (*x509.Certificate, *rsa.PrivateKey
return nil, nil, err
}

key, ok := tlsCert.PrivateKey.(*rsa.PrivateKey)
key, ok := tlsCert.PrivateKey.(crypto.Signer)
if !ok {
return nil, nil, fmt.Errorf("private key with unexpected type %T", key)
return nil, nil, fmt.Errorf("private key with unexpected type %T", tlsCert.PrivateKey)
}
return cert, key, nil
}
78 changes: 37 additions & 41 deletions cert/cert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
package cert_test

import (
"crypto/rsa"
"crypto/ed25519"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"testing"
"time"

jc "github.com/juju/testing/checkers"
"github.com/juju/utils/v3/cert"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v4/cert"
)

func TestAll(t *testing.T) {
Expand Down Expand Up @@ -58,7 +59,7 @@ func (certSuite) TestParseCertAndKey(c *gc.C) {
c.Assert(xcert.Subject.CommonName, gc.Equals, `juju-generated CA for model "juju testing"`)
c.Assert(key, gc.NotNil)

c.Assert(xcert.PublicKey.(*rsa.PublicKey), gc.DeepEquals, &key.PublicKey)
c.Assert(xcert.PublicKey, gc.DeepEquals, key.Public())
}

func (certSuite) TestNewCA(c *gc.C) {
Expand All @@ -73,7 +74,7 @@ func (certSuite) TestNewCA(c *gc.C) {
caCert, caKey, err := cert.ParseCertAndKey(caCertPEM, caKeyPEM)
c.Assert(err, jc.ErrorIsNil)

c.Check(caKey, gc.FitsTypeOf, (*rsa.PrivateKey)(nil))
c.Check(caKey, gc.FitsTypeOf, (ed25519.PrivateKey)(nil))
c.Check(caCert.Subject.CommonName, gc.Equals, `juju-generated CA for model foo`)
checkNotBefore(c, caCert, now)
checkNotAfter(c, caCert, expiry)
Expand All @@ -87,43 +88,38 @@ func roundTime(t time.Time) time.Time {
return t.Add(time.Duration(-t.Nanosecond()))
}

var rsaByteSizes = []int{512, 1024, 2048, 4096}

func (certSuite) TestNewClientCertRSASize(c *gc.C) {
for _, size := range rsaByteSizes {
now := time.Now()
expiry := roundTime(now.AddDate(0, 0, 1))
certPem, privPem, err := cert.NewClientCert(
fmt.Sprintf("juju-generated CA for model %s", "foo"), "1", expiry, size)

c.Assert(err, jc.ErrorIsNil)
c.Assert(certPem, gc.NotNil)
c.Assert(privPem, gc.NotNil)

caCert, caKey, err := cert.ParseCertAndKey(certPem, privPem)
c.Assert(err, jc.ErrorIsNil)
c.Check(caCert.Subject.CommonName, gc.Equals, "juju-generated CA for model foo")
c.Check(caCert.Subject.Organization, gc.DeepEquals, []string{"juju"})
c.Check(caCert.Subject.SerialNumber, gc.DeepEquals, "1")

c.Check(caKey, gc.FitsTypeOf, (*rsa.PrivateKey)(nil))
c.Check(caCert.Version, gc.Equals, 3)

value, err := cert.CertGetUPNExtenstionValue(caCert.Subject)
c.Assert(err, jc.ErrorIsNil)
c.Assert(value, gc.Not(gc.IsNil))

c.Assert(caCert.Extensions[len(caCert.Extensions)-1], jc.DeepEquals, pkix.Extension{
Id: cert.CertSubjAltName,
Value: value,
Critical: false,
})
c.Assert(caCert.PublicKeyAlgorithm, gc.Equals, x509.RSA)
c.Assert(caCert.ExtKeyUsage[0], gc.Equals, x509.ExtKeyUsageClientAuth)
checkNotBefore(c, caCert, now)
checkNotAfter(c, caCert, expiry)

}
func (certSuite) TestNewClientCert(c *gc.C) {
now := time.Now()
expiry := roundTime(now.AddDate(0, 0, 1))
certPem, privPem, err := cert.NewClientCert(
fmt.Sprintf("juju-generated CA for model %s", "foo"), "1", expiry)

c.Assert(err, jc.ErrorIsNil)
c.Assert(certPem, gc.NotNil)
c.Assert(privPem, gc.NotNil)

caCert, caKey, err := cert.ParseCertAndKey(certPem, privPem)
c.Assert(err, jc.ErrorIsNil)
c.Check(caCert.Subject.CommonName, gc.Equals, "juju-generated CA for model foo")
c.Check(caCert.Subject.Organization, gc.DeepEquals, []string{"juju"})
c.Check(caCert.Subject.SerialNumber, gc.DeepEquals, "1")

c.Check(caKey, gc.FitsTypeOf, (ed25519.PrivateKey)(nil))
c.Check(caCert.Version, gc.Equals, 3)

value, err := cert.CertGetUPNExtenstionValue(caCert.Subject)
c.Assert(err, jc.ErrorIsNil)
c.Assert(value, gc.Not(gc.IsNil))

c.Assert(caCert.Extensions[len(caCert.Extensions)-1], jc.DeepEquals, pkix.Extension{
Id: cert.CertSubjAltName,
Value: value,
Critical: false,
})
c.Assert(caCert.PublicKeyAlgorithm, gc.Equals, x509.Ed25519)
c.Assert(caCert.ExtKeyUsage[0], gc.Equals, x509.ExtKeyUsageClientAuth)
checkNotBefore(c, caCert, now)
checkNotAfter(c, caCert, expiry)
}

var (
Expand Down
2 changes: 1 addition & 1 deletion command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/juju/testing"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3"
"github.com/juju/utils/v4"
)

type EnvironmentPatcher interface {
Expand Down
2 changes: 1 addition & 1 deletion context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3"
"github.com/juju/utils/v4"
)

type contextSuite struct{}
Expand Down
32 changes: 32 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package utils

import (
"fmt"
)

// RcPassthroughError indicates that a Juju plugin command exited with a
// non-zero exit code. This error is used to exit with the return code.
type RcPassthroughError struct {
Code int
}

// Error implements error.
func (e *RcPassthroughError) Error() string {
return fmt.Sprintf("subprocess encountered error code %v", e.Code)
}

// IsRcPassthroughError returns whether the error is an RcPassthroughError.
func IsRcPassthroughError(err error) bool {
_, ok := err.(*RcPassthroughError)
return ok
}

// NewRcPassthroughError creates an error that will have the code used at the
// return code from the cmd.Main function rather than the default of 1 if
// there is an error.
func NewRcPassthroughError(code int) error {
return &RcPassthroughError{code}
}
2 changes: 1 addition & 1 deletion exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

"github.com/juju/clock"
"github.com/juju/errors"
"github.com/juju/loggo"
"github.com/juju/loggo/v2"
)

var logger = loggo.GetLogger("juju.util.exec")
Expand Down
2 changes: 1 addition & 1 deletion exec/exec_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3/exec"
"github.com/juju/utils/v4/exec"
)

// 0 is thrown by linux because RunParams.Wait
Expand Down
2 changes: 1 addition & 1 deletion exec/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
gc "gopkg.in/check.v1"

"github.com/juju/clock"
"github.com/juju/utils/v3/exec"
"github.com/juju/utils/v4/exec"
)

type execSuite struct {
Expand Down
2 changes: 1 addition & 1 deletion exec/exec_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3/exec"
"github.com/juju/utils/v4/exec"
)

// 1 is thrown by powershell after the a command is cancelled
Expand Down
2 changes: 1 addition & 1 deletion file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"

"github.com/juju/utils/v3"
"github.com/juju/utils/v4"
)

type fileSuite struct {
Expand Down
3 changes: 2 additions & 1 deletion file_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import (
gc "gopkg.in/check.v1"

"github.com/juju/errors"
"github.com/juju/utils/v3"

"github.com/juju/utils/v4"
)

type unixFileSuite struct {
Expand Down
Loading

0 comments on commit 56659c6

Please sign in to comment.