File: signer.go

package info (click to toggle)
golang-github-googleapis-enterprise-certificate-proxy 0.3.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 428 kB
  • sloc: sh: 87; makefile: 11
file content (132 lines) | stat: -rw-r--r-- 3,606 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2022 Google LLC.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// signer.go is a net/rpc server that listens on stdin/stdout, exposing
// mock methods for testing client.go.
package main

import (
	"crypto"
	"crypto/tls"
	"crypto/x509"
	"io"
	"log"
	"net/rpc"
	"os"
	"time"
)

// SignArgs encapsulate the parameters for the Sign method.
type SignArgs struct {
	Digest []byte
	Opts   crypto.SignerOpts
}

// EncryptArgs encapsulate the parameters for the Encrypt method.
type EncryptArgs struct {
	Plaintext []byte
}

// DecryptArgs encapsulate the parameters for the Decrypt method.
type DecryptArgs struct {
	Ciphertext []byte
}

// EnterpriseCertSigner exports RPC methods for signing.
type EnterpriseCertSigner struct {
	cert *tls.Certificate
}

// Connection wraps a pair of unidirectional streams as an io.ReadWriteCloser.
type Connection struct {
	io.ReadCloser
	io.WriteCloser
}

// Close closes c's underlying ReadCloser and WriteCloser.
func (c *Connection) Close() error {
	rerr := c.ReadCloser.Close()
	werr := c.WriteCloser.Close()
	if rerr != nil {
		return rerr
	}
	return werr
}

// CertificateChain returns the credential as a raw X509 cert chain. This
// contains the public key.
func (k *EnterpriseCertSigner) CertificateChain(ignored struct{}, certificateChain *[][]byte) error {
	*certificateChain = k.cert.Certificate
	return nil
}

// Public returns the first public key for this Key, in ASN.1 DER form.
func (k *EnterpriseCertSigner) Public(ignored struct{}, publicKey *[]byte) (err error) {
	if len(k.cert.Certificate) == 0 {
		return nil
	}
	cert, err := x509.ParseCertificate(k.cert.Certificate[0])
	if err != nil {
		return err
	}
	*publicKey, err = x509.MarshalPKIXPublicKey(cert.PublicKey)
	return err
}

// Sign signs a message digest. For testing, we return the input as-is.
func (k *EnterpriseCertSigner) Sign(args SignArgs, resp *[]byte) (err error) {
	*resp = args.Digest
	return nil
}

// Encrypt encrypts a plaintext msg. For testing, we return the input as-is.
func (k *EnterpriseCertSigner) Encrypt(args EncryptArgs, plaintext *[]byte) (err error) {
	*plaintext = args.Plaintext
	return nil
}

// Decrypt decrypts a ciphertext msg. For testing, we return the input as-is.
func (k *EnterpriseCertSigner) Decrypt(args DecryptArgs, ciphertext *[]byte) (err error) {
	*ciphertext = args.Ciphertext
	return nil
}

func main() {
	enterpriseCertSigner := new(EnterpriseCertSigner)

	data, err := os.ReadFile(os.Args[1])
	if err != nil {
		log.Fatalf("Error reading certificate: %v", err)
	}
	cert, _ := tls.X509KeyPair(data, data)

	enterpriseCertSigner.cert = &cert

	if err := rpc.Register(enterpriseCertSigner); err != nil {
		log.Fatalf("Error registering net/rpc: %v", err)
	}

	// If the parent process dies, we should exit.
	// We can detect this by periodically checking if the PID of the parent
	// process is 1 (https://stackoverflow.com/a/2035683).
	go func() {
		for {
			if os.Getppid() == 1 {
				log.Fatalln("Parent process died, exiting...")
			}
			time.Sleep(time.Second)
		}
	}()

	rpc.ServeConn(&Connection{os.Stdin, os.Stdout})
}