Skip to content

Commit

Permalink
changed to use spiffe-csi
Browse files Browse the repository at this point in the history
  • Loading branch information
pxp928 committed Feb 7, 2022
1 parent d45939a commit 2b69aa9
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 61 deletions.
19 changes: 10 additions & 9 deletions cmd/imagedigestexporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,17 @@ func main() {
}
ctx := context.Background()

client, err := workloadapi.New(ctx, workloadapi.WithAddr("unix:///run/spire/sockets/agent.sock"))
if err != nil {
logger.Fatal(err)
}
signed, err := entrypoint.Sign(output, client)
if err != nil {
logger.Fatal(err)
}
client, err := workloadapi.New(ctx, workloadapi.WithAddr("unix:///spiffe-workload-api/spire-agent.sock"))
if err == nil {
signed, err := entrypoint.Sign(output, client)
if err != nil {
logger.Fatal(err)
}

output = append(output, signed...)
output = append(output, signed...)
} else {
logger.Infof("Spire workload API not initalized due to error: %s", err.Error())
}

if err := termination.WriteMessage(*terminationMessagePath, output); err != nil {
logger.Fatalf("Unexpected error writing message %s to %s", *terminationMessagePath, err)
Expand Down
11 changes: 5 additions & 6 deletions config/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ spec:
mountPath: /etc/config-logging
- name: config-registry-cert
mountPath: /etc/config-registry-cert
- name: spire
mountPath: /run/spire/sockets
- name: spiffe-workload-api
mountPath: /spiffe-workload-api
readOnly: true
env:
- name: SYSTEM_NAMESPACE
Expand Down Expand Up @@ -157,10 +157,9 @@ spec:
- name: config-registry-cert
configMap:
name: config-registry-cert
- name: spire
hostPath:
path: /run/spire/sockets
type: Directory
- name: spiffe-workload-api
csi:
driver: "csi.spiffe.io"
---
apiVersion: v1
kind: Service
Expand Down
56 changes: 39 additions & 17 deletions pkg/entrypoint/entrypointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,26 +145,26 @@ func (e Entrypointer) Go() error {

ctx := context.Background()
var err error
var client *workloadapi.Client
var client *workloadapi.Client = nil

client, err = workloadapi.New(ctx, workloadapi.WithAddr("unix:///run/spire/sockets/agent.sock"))
if err != nil {
return err
}
jwt, err := client.FetchJWTSVID(ctx, jwtsvid.Params{
Audience: "sigstore",
})
if err != nil {
return err
client, err = workloadapi.New(ctx, workloadapi.WithAddr("unix:///spiffe-workload-api/spire-agent.sock"))
if err == nil {
jwt, err := client.FetchJWTSVID(ctx, jwtsvid.Params{
Audience: "sigstore",
})
if err != nil {
return err
}
logger.Infof("Obtained JWT from spire - %s", jwt.ID)
} else {
logger.Infof("Spire workload API not initalized due to error: %s", err.Error())
}
logger.Info("Obtained JWT from spire - %s", jwt.ID)

if e.Timeout != nil && *e.Timeout < time.Duration(0) {
err = fmt.Errorf("negative timeout specified")
}

if err == nil {
ctx := context.Background()
var cancel context.CancelFunc
if e.Timeout != nil && *e.Timeout != time.Duration(0) {
ctx, cancel = context.WithTimeout(ctx, *e.Timeout)
Expand Down Expand Up @@ -215,11 +215,18 @@ func (e Entrypointer) Go() error {
}

func Sign(results []v1beta1.PipelineResourceResult, client *workloadapi.Client) ([]v1beta1.PipelineResourceResult, error) {

xsvid, err := client.FetchX509SVID(context.Background())
if err != nil {
return nil, err
}
x509set, err := client.FetchX509Bundles(context.Background())
if err != nil {
return nil, err
}
x509Bundle := x509set.Bundles()
if err != nil {
return nil, err
}
output := []v1beta1.PipelineResourceResult{}
if len(results) > 1 {
p := pem.EncodeToMemory(&pem.Block{
Expand All @@ -231,6 +238,19 @@ func Sign(results []v1beta1.PipelineResourceResult, client *workloadapi.Client)
Value: string(p),
ResultType: v1beta1.TaskRunResultType,
})
var trust []byte
for _, c := range x509Bundle[0].X509Authorities() {
inter := pem.EncodeToMemory(&pem.Block{
Bytes: c.Raw,
Type: "CERTIFICATE",
})
trust = append(trust, inter...)
}
output = append(output, v1beta1.PipelineResourceResult{
Key: "TRUST_BUNDLE",
Value: string(trust),
ResultType: v1beta1.TaskRunResultType,
})
}
for _, r := range results {
dgst := sha256.Sum256([]byte(r.Value))
Expand Down Expand Up @@ -268,11 +288,13 @@ func (e Entrypointer) readResultsFromDisk(client *workloadapi.Client) error {
})
}

signed, err := Sign(output, client)
if err != nil {
return err
if client != nil {
signed, err := Sign(output, client)
if err != nil {
return err
}
output = append(output, signed...)
}
output = append(output, signed...)

// push output to termination path
if len(output) != 0 {
Expand Down
16 changes: 7 additions & 9 deletions pkg/pod/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,29 +276,27 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1beta1.TaskRun, taskSpec
}

if config.FromContextOrDefaults(ctx).FeatureFlags.EnableSpire {
typ := corev1.HostPathSocket
volumes = append(volumes, corev1.Volume{
Name: "spire",
Name: "spiffe-workload-api",
VolumeSource: corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/run/spire/sockets/agent.sock",
Type: &typ,
CSI: &corev1.CSIVolumeSource{
Driver: "csi.spiffe.io",
},
},
})
//podName := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("%s-pod", taskRun.Name))
for i := range stepContainers {
c := &stepContainers[i]
c.VolumeMounts = append(c.VolumeMounts, corev1.VolumeMount{
Name: "spire",
MountPath: "/run/spire/sockets/agent.sock",
Name: "spiffe-workload-api",
MountPath: "/spiffe-workload-api",
})
}
for i := range initContainers {
c := &initContainers[i]
c.VolumeMounts = append(c.VolumeMounts, corev1.VolumeMount{
Name: "spire",
MountPath: "/run/spire/sockets/agent.sock",
Name: "spiffe-workload-api",
MountPath: "/spiffe-workload-api",
})
}

Expand Down
95 changes: 75 additions & 20 deletions pkg/pod/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,22 +163,28 @@ func setTaskRunStatusBasedOnStepStatus(logger *zap.SugaredLogger, stepStatuses [
merr = multierror.Append(merr, err)

} else {

if err := checkValidated(results); err != nil {
trs.SetCondition(&apis.Condition{
Type: "VERIFIED",
Status: corev1.ConditionFalse,
Reason: "checked signatures",
Message: err.Error(),
})
} else {
trs.SetCondition(&apis.Condition{
Type: "VERIFIED",
Status: corev1.ConditionTrue,
Reason: "checked signatures",
Message: "everything is cool",
})
logger.Info("Results: ", results)
if tr.IsSuccessful() {
if len(results) >= 1 && results[0].Key != "StartedAt" {
logger.Info("Validating Results with spire: ", results)
if err := checkValidated(results); err != nil {
trs.SetCondition(&apis.Condition{
Type: "VERIFICATION FAILED",
Status: corev1.ConditionFalse,
Reason: "signatures verification failure",
Message: err.Error(),
})
} else {
trs.SetCondition(&apis.Condition{
Type: "VERIFIED",
Status: corev1.ConditionTrue,
Reason: "checked signatures",
Message: "Spire verified signature",
})
}
}
}

time, err := extractStartedAtTimeFromResults(results)
if err != nil {
logger.Errorf("error setting the start time of step %q in taskrun %q: %v", s.Name, tr.Name, err)
Expand Down Expand Up @@ -227,12 +233,16 @@ func checkValidated(rs []v1beta1.PipelineResourceResult) error {
for _, r := range rs {
resultMap[r.Key] = r
}
svid, ok := resultMap["SVID"]
if !ok {
return errors.New("No SVID found")

cert, err := getSVID(resultMap)
if err != nil {
return err
}

trust, err := getTrustBundle(resultMap)
if err != nil {
return err
}
block, _ := pem.Decode([]byte(svid.Value))
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return fmt.Errorf("invalid SVID: %s", err)
}
Expand All @@ -244,17 +254,62 @@ func checkValidated(rs []v1beta1.PipelineResourceResult) error {
if key == "SVID" {
continue
}
if key == "TRUST_BUNDLE" {
continue
}
if val.ResultType == v1beta1.InternalTektonResultType {
continue
}
if err := verifyOne(cert.PublicKey, key, resultMap); err != nil {
return err
}
if err := verifyCertificateTrust(cert, trust); err != nil {
return err
}
}

return nil
}

func getSVID(resultMap map[string]v1beta1.PipelineResourceResult) (*x509.Certificate, error) {
svid, ok := resultMap["SVID"]
if !ok {
return nil, errors.New("no SVID found")
}
block, _ := pem.Decode([]byte(svid.Value))
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("invalid SVID: %s", err)
}
return cert, nil
}

func getTrustBundle(resultMap map[string]v1beta1.PipelineResourceResult) (*x509.CertPool, error) {
bundle, ok := resultMap["TRUST_BUNDLE"]
if !ok {
return nil, errors.New("no Spire Trust Bundle found")
}
block, _ := pem.Decode([]byte(bundle.Value))
trustPool := x509.NewCertPool()
trust, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("invalid trust bundle: %s", err)
}
trustPool.AddCert(trust)
return trustPool, nil
}

func verifyCertificateTrust(cert *x509.Certificate, rootCertPool *x509.CertPool) error {
verifyOptions := x509.VerifyOptions{
Roots: rootCertPool,
}
chains, err := cert.Verify(verifyOptions)
if len(chains) == 0 || err != nil {
return fmt.Errorf("cert cannot be verified by provided roots")
}
return nil
}

func verifyOne(pub interface{}, key string, results map[string]v1beta1.PipelineResourceResult) error {
signature, ok := results[key+".sig"]
if !ok {
Expand Down

0 comments on commit 2b69aa9

Please sign in to comment.