Skip to content

Commit

Permalink
Expose all service-account keys through OIDC
Browse files Browse the repository at this point in the history
  • Loading branch information
johngmyers committed Apr 13, 2021
1 parent 3a61039 commit a167732
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 45 deletions.
44 changes: 19 additions & 25 deletions pkg/model/awsmodel/oidc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"sort"

"gopkg.in/square/go-jose.v2"
"k8s.io/kops/pkg/featureflag"
Expand Down Expand Up @@ -152,40 +152,34 @@ func (o *OIDCKeys) GetDependencies(tasks map[string]fi.Task) []fi.Task {
o.SigningKey,
}
}
func (o *OIDCKeys) Open() (io.Reader, error) {

certBytes, err := fi.ResourceAsBytes(o.SigningKey.Certificate())
if err != nil {
return nil, fmt.Errorf("failed to get cert: %w", err)
}
block, _ := pem.Decode(certBytes)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse cert: %w", err)
}

publicKey := cert.PublicKey
func (o *OIDCKeys) Open() (io.Reader, error) {
keyset := o.SigningKey.Keyset()
var keys []jose.JSONWebKey

publicKeyDERBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, fmt.Errorf("failed to serialize public key to DER format: %v", err)
}
for _, item := range keyset.Items {
publicKey := item.Certificate.PublicKey
publicKeyDERBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, fmt.Errorf("failed to serialize public key to DER format: %v", err)
}

hasher := crypto.SHA256.New()
hasher.Write(publicKeyDERBytes)
publicKeyDERHash := hasher.Sum(nil)
hasher := crypto.SHA256.New()
hasher.Write(publicKeyDERBytes)
publicKeyDERHash := hasher.Sum(nil)

keyID := base64.RawURLEncoding.EncodeToString(publicKeyDERHash)
keyID := base64.RawURLEncoding.EncodeToString(publicKeyDERHash)

keys := []jose.JSONWebKey{
{
keys = append(keys, jose.JSONWebKey{
Key: publicKey,
KeyID: keyID,
Algorithm: string(jose.RS256),
Use: "sig",
},
})
}

sort.Slice(keys, func(i, j int) bool {
return keys[i].KeyID < keys[j].KeyID
})
keyResponse := KeyResponse{Keys: keys}
jsonBytes, err := json.MarshalIndent(keyResponse, "", "")
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/model/bootstrapscript.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ func (b *BootstrapScriptBuilder) ResourceNodeUp(c *fi.ModelBuilderContext, ig *k
ig: ig,
builder: b,
caTask: caTask,
ca: caTask.Certificate(),
// TODO: use caTask.Keyset() and expose all CA certificates
ca: caTask.Certificate(),
}
task.resource.Task = task
c.AddTask(task)
Expand Down
31 changes: 12 additions & 19 deletions upup/pkg/fi/fitasks/keypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package fitasks

import (
"crypto/sha1"
"crypto/x509/pkix"
"fmt"
"sort"
Expand Down Expand Up @@ -46,8 +45,8 @@ type Keypair struct {
// LegacyFormat is whether the keypair is stored in a legacy format.
LegacyFormat bool `json:"oldFormat"`

certificate *fi.TaskDependentResource
certificateSHA1Fingerprint *fi.TaskDependentResource
certificate *fi.TaskDependentResource
keyset *fi.Keyset
}

var _ fi.HasCheckExisting = &Keypair{}
Expand Down Expand Up @@ -103,7 +102,7 @@ func (e *Keypair) Find(c *fi.Context) (*Keypair, error) {
// Avoid spurious changes
actual.Lifecycle = e.Lifecycle

if err := e.setResources(cert); err != nil {
if err := e.setResources(keyset); err != nil {
return nil, fmt.Errorf("error setting resources: %v", err)
}

Expand Down Expand Up @@ -233,18 +232,19 @@ func (_ *Keypair) Render(c *fi.Context, a, e, changes *Keypair) error {
PrivateKey: privateKey,
}

err = c.Keystore.StoreKeypair(name, &fi.Keyset{
keyset = &fi.Keyset{
LegacyFormat: false,
Items: map[string]*fi.KeysetItem{
serialString: ki,
},
Primary: ki,
})
}
err = c.Keystore.StoreKeypair(name, keyset)
if err != nil {
return err
}

if err := e.setResources(cert); err != nil {
if err := e.setResources(keyset); err != nil {
return fmt.Errorf("error setting resources: %v", err)
}

Expand Down Expand Up @@ -308,30 +308,23 @@ func (e *Keypair) ensureResources() {
if e.certificate == nil {
e.certificate = &fi.TaskDependentResource{Task: e}
}
if e.certificateSHA1Fingerprint == nil {
e.certificateSHA1Fingerprint = &fi.TaskDependentResource{Task: e}
}
}

func (e *Keypair) setResources(cert *pki.Certificate) error {
func (e *Keypair) setResources(keyset *fi.Keyset) error {
e.ensureResources()

s, err := cert.AsString()
s, err := keyset.Primary.Certificate.AsString()
if err != nil {
return err
}
e.certificate.Resource = fi.NewStringResource(s)

fingerprint := sha1.Sum(cert.Certificate.Raw)
hex := fmt.Sprintf("%x", fingerprint)
e.certificateSHA1Fingerprint.Resource = fi.NewStringResource(hex)

e.keyset = keyset
return nil
}

func (e *Keypair) CertificateSHA1Fingerprint() fi.Resource {
e.ensureResources()
return e.certificateSHA1Fingerprint
func (e *Keypair) Keyset() *fi.Keyset {
return e.keyset
}

func (e *Keypair) Certificate() fi.Resource {
Expand Down

0 comments on commit a167732

Please sign in to comment.