From 07097ca699d554b743df105a9faa915d7dc3c477 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 29 Dec 2021 15:40:58 -0800 Subject: [PATCH 1/5] Add keys to set certificates and certificate chains in the templates --- sshutil/templates.go | 14 ++++++++ sshutil/templates_test.go | 74 ++++++++++++++++++++++++++++++++++++++ x509util/templates.go | 14 ++++++++ x509util/templates_test.go | 74 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) diff --git a/sshutil/templates.go b/sshutil/templates.go index 84a05ec4..d0f78bd0 100644 --- a/sshutil/templates.go +++ b/sshutil/templates.go @@ -11,6 +11,8 @@ const ( InsecureKey = "Insecure" UserKey = "User" CertificateRequestKey = "CR" + CertificateKey = "Crt" + CertificateChainKey = "Chain" ) // TemplateError represents an error in a template produced by the fail @@ -134,6 +136,18 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } +// SetCertificate sets a the given certificate in the template. This certificate +// is generally present in a token header. +func (t TemplateData) SetCertificate(crt interface{}) { + t.Set(CertificateKey, crt) +} + +// SetCertificateChain sets a the given certificate chain in the template. These +// certificates are generally present in a token header. +func (t TemplateData) SetCertificateChain(chain interface{}) { + t.Set(CertificateChainKey, chain) +} + // SetCertificateRequest sets the simulated ssh certificate request the insecure // template data. func (t TemplateData) SetCertificateRequest(cr CertificateRequest) { diff --git a/sshutil/templates_test.go b/sshutil/templates_test.go index ac4152b5..d12f47a7 100644 --- a/sshutil/templates_test.go +++ b/sshutil/templates_test.go @@ -441,6 +441,80 @@ func TestTemplateData_SetUserData(t *testing.T) { } } +func TestTemplateData_SetCertificate(t *testing.T) { + crt1 := Certificate{Key: mustGeneratePublicKey(t)} + crt2 := Certificate{Key: mustGeneratePublicKey(t)} + type args struct { + crt Certificate + } + tests := []struct { + name string + t TemplateData + args args + want TemplateData + }{ + {"ok", TemplateData{}, args{crt1}, TemplateData{ + CertificateKey: crt1, + }}, + {"overwrite", TemplateData{ + CertificateKey: crt1, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }, args{crt2}, TemplateData{ + CertificateKey: crt2, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.t.SetCertificate(tt.args.crt) + if !reflect.DeepEqual(tt.t, tt.want) { + t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) + } + }) + } +} + +func TestTemplateData_SetCertificateChain(t *testing.T) { + crt1 := Certificate{Key: mustGeneratePublicKey(t)} + crt2 := Certificate{Key: mustGeneratePublicKey(t)} + type args struct { + crt []interface{} + } + tests := []struct { + name string + t TemplateData + args args + want TemplateData + }{ + {"ok", TemplateData{}, args{[]interface{}{crt1, crt2}}, TemplateData{ + CertificateChainKey: []interface{}{crt1, crt2}, + }}, + {"overwrite", TemplateData{ + CertificateChainKey: []interface{}{crt1, crt2}, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }, args{[]interface{}{crt1}}, TemplateData{ + CertificateChainKey: []interface{}{crt1}, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.t.SetCertificateChain(tt.args.crt) + if !reflect.DeepEqual(tt.t, tt.want) { + t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) + } + }) + } +} + func TestTemplateData_SetCertificateRequest(t *testing.T) { cr1 := CertificateRequest{Key: mustGeneratePublicKey(t)} cr2 := CertificateRequest{Key: mustGeneratePublicKey(t)} diff --git a/x509util/templates.go b/x509util/templates.go index bdfce603..663ea0c8 100644 --- a/x509util/templates.go +++ b/x509util/templates.go @@ -12,6 +12,8 @@ const ( InsecureKey = "Insecure" UserKey = "User" CertificateRequestKey = "CR" + CertificateKey = "Crt" + CertificateChainKey = "Chain" ) // TemplateError represents an error in a template produced by the fail @@ -87,6 +89,18 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } +// SetCertificate sets a the given certificate in the template. This certificate +// is generally present in a token header. +func (t TemplateData) SetCertificate(crt interface{}) { + t.Set(CertificateKey, crt) +} + +// SetCertificateChain sets a the given certificate chain in the template. These +// certificates are generally present in a token header. +func (t TemplateData) SetCertificateChain(chain interface{}) { + t.Set(CertificateChainKey, chain) +} + // SetCertificateRequest sets the given certificate request in the insecure // template data. func (t TemplateData) SetCertificateRequest(cr *x509.CertificateRequest) { diff --git a/x509util/templates_test.go b/x509util/templates_test.go index c5f66a97..5e9b9c26 100644 --- a/x509util/templates_test.go +++ b/x509util/templates_test.go @@ -226,6 +226,80 @@ func TestTemplateData_SetUserData(t *testing.T) { } } +func TestTemplateData_SetCertificate(t *testing.T) { + crt1 := Certificate{DNSNames: []string{"crt1"}} + crt2 := Certificate{DNSNames: []string{"crt2"}} + type args struct { + crt Certificate + } + tests := []struct { + name string + t TemplateData + args args + want TemplateData + }{ + {"ok", TemplateData{}, args{crt1}, TemplateData{ + CertificateKey: crt1, + }}, + {"overwrite", TemplateData{ + CertificateKey: crt1, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }, args{crt2}, TemplateData{ + CertificateKey: crt2, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.t.SetCertificate(tt.args.crt) + if !reflect.DeepEqual(tt.t, tt.want) { + t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) + } + }) + } +} + +func TestTemplateData_SetCertificateChain(t *testing.T) { + crt1 := Certificate{DNSNames: []string{"crt1"}} + crt2 := Certificate{DNSNames: []string{"crt2"}} + type args struct { + crt []interface{} + } + tests := []struct { + name string + t TemplateData + args args + want TemplateData + }{ + {"ok", TemplateData{}, args{[]interface{}{crt1, crt2}}, TemplateData{ + CertificateChainKey: []interface{}{crt1, crt2}, + }}, + {"overwrite", TemplateData{ + CertificateChainKey: []interface{}{crt1, crt2}, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }, args{[]interface{}{crt1}}, TemplateData{ + CertificateChainKey: []interface{}{crt1}, + InsecureKey: TemplateData{ + UserKey: "data", + }, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.t.SetCertificateChain(tt.args.crt) + if !reflect.DeepEqual(tt.t, tt.want) { + t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) + } + }) + } +} + func TestTemplateData_SetCertificateRequest(t *testing.T) { cr := &x509.CertificateRequest{ DNSNames: []string{"foo", "bar"}, From b9132b15893f3748d85125368c9b045e7283a6cc Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 3 Jan 2022 12:16:03 -0800 Subject: [PATCH 2/5] fix typo in comment. --- sshutil/templates.go | 2 +- x509util/templates.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sshutil/templates.go b/sshutil/templates.go index d0f78bd0..f78985e7 100644 --- a/sshutil/templates.go +++ b/sshutil/templates.go @@ -136,7 +136,7 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } -// SetCertificate sets a the given certificate in the template. This certificate +// SetCertificate sets the given certificate in the template. This certificate // is generally present in a token header. func (t TemplateData) SetCertificate(crt interface{}) { t.Set(CertificateKey, crt) diff --git a/x509util/templates.go b/x509util/templates.go index 663ea0c8..3e6b552c 100644 --- a/x509util/templates.go +++ b/x509util/templates.go @@ -89,7 +89,7 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } -// SetCertificate sets a the given certificate in the template. This certificate +// SetCertificate sets the given certificate in the template. This certificate // is generally present in a token header. func (t TemplateData) SetCertificate(crt interface{}) { t.Set(CertificateKey, crt) From f6bddce7f495e3a7a309d7a15d32bcc537d8c444 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 3 Jan 2022 12:33:19 -0800 Subject: [PATCH 3/5] Use AuthorizationCrt and AuthorizationChain template variables. --- sshutil/templates.go | 20 ++++++++++---------- sshutil/templates_test.go | 20 ++++++++++---------- x509util/templates.go | 18 +++++++++--------- x509util/templates_test.go | 20 ++++++++++---------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/sshutil/templates.go b/sshutil/templates.go index f78985e7..b6adc704 100644 --- a/sshutil/templates.go +++ b/sshutil/templates.go @@ -11,8 +11,8 @@ const ( InsecureKey = "Insecure" UserKey = "User" CertificateRequestKey = "CR" - CertificateKey = "Crt" - CertificateChainKey = "Chain" + AuthorizationCrtKey = "AuthorizationCrt" + AuthorizationChainKey = "AuthorizationChain" ) // TemplateError represents an error in a template produced by the fail @@ -136,16 +136,16 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } -// SetCertificate sets the given certificate in the template. This certificate -// is generally present in a token header. -func (t TemplateData) SetCertificate(crt interface{}) { - t.Set(CertificateKey, crt) +// SetAuthorizationCertificate sets the given certificate in the template. This +// certificate is generally present in a token header. +func (t TemplateData) SetAuthorizationCertificate(crt interface{}) { + t.Set(AuthorizationCrtKey, crt) } -// SetCertificateChain sets a the given certificate chain in the template. These -// certificates are generally present in a token header. -func (t TemplateData) SetCertificateChain(chain interface{}) { - t.Set(CertificateChainKey, chain) +// SetAuthorizationCertificateChain sets a the given certificate chain in the +// template. These certificates are generally present in a token header. +func (t TemplateData) SetAuthorizationCertificateChain(chain interface{}) { + t.Set(AuthorizationChainKey, chain) } // SetCertificateRequest sets the simulated ssh certificate request the insecure diff --git a/sshutil/templates_test.go b/sshutil/templates_test.go index d12f47a7..8981d8e1 100644 --- a/sshutil/templates_test.go +++ b/sshutil/templates_test.go @@ -441,7 +441,7 @@ func TestTemplateData_SetUserData(t *testing.T) { } } -func TestTemplateData_SetCertificate(t *testing.T) { +func TestTemplateData_SetAuthorizationCertificate(t *testing.T) { crt1 := Certificate{Key: mustGeneratePublicKey(t)} crt2 := Certificate{Key: mustGeneratePublicKey(t)} type args struct { @@ -454,15 +454,15 @@ func TestTemplateData_SetCertificate(t *testing.T) { want TemplateData }{ {"ok", TemplateData{}, args{crt1}, TemplateData{ - CertificateKey: crt1, + AuthorizationCrtKey: crt1, }}, {"overwrite", TemplateData{ - CertificateKey: crt1, + AuthorizationCrtKey: crt1, InsecureKey: TemplateData{ UserKey: "data", }, }, args{crt2}, TemplateData{ - CertificateKey: crt2, + AuthorizationCrtKey: crt2, InsecureKey: TemplateData{ UserKey: "data", }, @@ -470,7 +470,7 @@ func TestTemplateData_SetCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.t.SetCertificate(tt.args.crt) + tt.t.SetAuthorizationCertificate(tt.args.crt) if !reflect.DeepEqual(tt.t, tt.want) { t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) } @@ -478,7 +478,7 @@ func TestTemplateData_SetCertificate(t *testing.T) { } } -func TestTemplateData_SetCertificateChain(t *testing.T) { +func TestTemplateData_SetAuthorizationCertificateChain(t *testing.T) { crt1 := Certificate{Key: mustGeneratePublicKey(t)} crt2 := Certificate{Key: mustGeneratePublicKey(t)} type args struct { @@ -491,15 +491,15 @@ func TestTemplateData_SetCertificateChain(t *testing.T) { want TemplateData }{ {"ok", TemplateData{}, args{[]interface{}{crt1, crt2}}, TemplateData{ - CertificateChainKey: []interface{}{crt1, crt2}, + AuthorizationChainKey: []interface{}{crt1, crt2}, }}, {"overwrite", TemplateData{ - CertificateChainKey: []interface{}{crt1, crt2}, + AuthorizationChainKey: []interface{}{crt1, crt2}, InsecureKey: TemplateData{ UserKey: "data", }, }, args{[]interface{}{crt1}}, TemplateData{ - CertificateChainKey: []interface{}{crt1}, + AuthorizationChainKey: []interface{}{crt1}, InsecureKey: TemplateData{ UserKey: "data", }, @@ -507,7 +507,7 @@ func TestTemplateData_SetCertificateChain(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.t.SetCertificateChain(tt.args.crt) + tt.t.SetAuthorizationCertificateChain(tt.args.crt) if !reflect.DeepEqual(tt.t, tt.want) { t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) } diff --git a/x509util/templates.go b/x509util/templates.go index 3e6b552c..48457007 100644 --- a/x509util/templates.go +++ b/x509util/templates.go @@ -12,8 +12,8 @@ const ( InsecureKey = "Insecure" UserKey = "User" CertificateRequestKey = "CR" - CertificateKey = "Crt" - CertificateChainKey = "Chain" + AuthorizationCrtKey = "AuthorizationCrt" + AuthorizationChainKey = "AuthorizationChain" ) // TemplateError represents an error in a template produced by the fail @@ -89,16 +89,16 @@ func (t TemplateData) SetUserData(v interface{}) { t.SetInsecure(UserKey, v) } -// SetCertificate sets the given certificate in the template. This certificate +// SetAuthorizationCertificate sets the given certificate in the template. This certificate // is generally present in a token header. -func (t TemplateData) SetCertificate(crt interface{}) { - t.Set(CertificateKey, crt) +func (t TemplateData) SetAuthorizationCertificate(crt interface{}) { + t.Set(AuthorizationCrtKey, crt) } -// SetCertificateChain sets a the given certificate chain in the template. These -// certificates are generally present in a token header. -func (t TemplateData) SetCertificateChain(chain interface{}) { - t.Set(CertificateChainKey, chain) +// SetAuthorizationCertificateChain sets a the given certificate chain in the +// template. These certificates are generally present in a token header. +func (t TemplateData) SetAuthorizationCertificateChain(chain interface{}) { + t.Set(AuthorizationChainKey, chain) } // SetCertificateRequest sets the given certificate request in the insecure diff --git a/x509util/templates_test.go b/x509util/templates_test.go index 5e9b9c26..a957654c 100644 --- a/x509util/templates_test.go +++ b/x509util/templates_test.go @@ -226,7 +226,7 @@ func TestTemplateData_SetUserData(t *testing.T) { } } -func TestTemplateData_SetCertificate(t *testing.T) { +func TestTemplateData_SetAuthorizationCertificate(t *testing.T) { crt1 := Certificate{DNSNames: []string{"crt1"}} crt2 := Certificate{DNSNames: []string{"crt2"}} type args struct { @@ -239,15 +239,15 @@ func TestTemplateData_SetCertificate(t *testing.T) { want TemplateData }{ {"ok", TemplateData{}, args{crt1}, TemplateData{ - CertificateKey: crt1, + AuthorizationCrtKey: crt1, }}, {"overwrite", TemplateData{ - CertificateKey: crt1, + AuthorizationCrtKey: crt1, InsecureKey: TemplateData{ UserKey: "data", }, }, args{crt2}, TemplateData{ - CertificateKey: crt2, + AuthorizationCrtKey: crt2, InsecureKey: TemplateData{ UserKey: "data", }, @@ -255,7 +255,7 @@ func TestTemplateData_SetCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.t.SetCertificate(tt.args.crt) + tt.t.SetAuthorizationCertificate(tt.args.crt) if !reflect.DeepEqual(tt.t, tt.want) { t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) } @@ -263,7 +263,7 @@ func TestTemplateData_SetCertificate(t *testing.T) { } } -func TestTemplateData_SetCertificateChain(t *testing.T) { +func TestTemplateData_SetAuthorizationCertificateChain(t *testing.T) { crt1 := Certificate{DNSNames: []string{"crt1"}} crt2 := Certificate{DNSNames: []string{"crt2"}} type args struct { @@ -276,15 +276,15 @@ func TestTemplateData_SetCertificateChain(t *testing.T) { want TemplateData }{ {"ok", TemplateData{}, args{[]interface{}{crt1, crt2}}, TemplateData{ - CertificateChainKey: []interface{}{crt1, crt2}, + AuthorizationChainKey: []interface{}{crt1, crt2}, }}, {"overwrite", TemplateData{ - CertificateChainKey: []interface{}{crt1, crt2}, + AuthorizationChainKey: []interface{}{crt1, crt2}, InsecureKey: TemplateData{ UserKey: "data", }, }, args{[]interface{}{crt1}}, TemplateData{ - CertificateChainKey: []interface{}{crt1}, + AuthorizationChainKey: []interface{}{crt1}, InsecureKey: TemplateData{ UserKey: "data", }, @@ -292,7 +292,7 @@ func TestTemplateData_SetCertificateChain(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.t.SetCertificateChain(tt.args.crt) + tt.t.SetAuthorizationCertificateChain(tt.args.crt) if !reflect.DeepEqual(tt.t, tt.want) { t.Errorf("TemplateData.SetCertificate() = %v, want %v", tt.t, tt.want) } From 74b0c4b02d9fc116e2f23b2844659de77a64f2ef Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 3 Jan 2022 18:03:48 -0800 Subject: [PATCH 4/5] Fix x25519.PrivateKey.Public() return so it implements crypto.Signer --- x25519/x25519.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x25519/x25519.go b/x25519/x25519.go index ca0879e1..5e3d2b60 100644 --- a/x25519/x25519.go +++ b/x25519/x25519.go @@ -61,7 +61,7 @@ func (p PublicKey) ToEd25519() (ed25519.PublicKey, error) { // Public returns the public key using scalar multiplication (scalar * point) // using the Curve25519 basepoint. It will return nil if the private key is not // a valid one. -func (p PrivateKey) Public() PublicKey { +func (p PrivateKey) Public() crypto.PublicKey { pub, _ := p.PublicKey() return pub } From cfaa65f61443983dc5de793c1813858a67dc6da8 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 3 Jan 2022 18:07:40 -0800 Subject: [PATCH 5/5] Fix x25519 thumbprint --- jose/generate.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jose/generate.go b/jose/generate.go index 49760b93..29fe72a6 100644 --- a/jose/generate.go +++ b/jose/generate.go @@ -41,7 +41,10 @@ func Thumbprint(jwk *JSONWebKey) (string, error) { case x25519.PublicKey: sum, err = x25519Thumbprint(key, crypto.SHA256) case x25519.PrivateKey: - sum, err = x25519Thumbprint(key.Public(), crypto.SHA256) + var pub x25519.PublicKey + if pub, err = key.PublicKey(); err == nil { + sum, err = x25519Thumbprint(pub, crypto.SHA256) + } default: sum, err = jwk.Thumbprint(crypto.SHA256) }