1package atccmd 2 3import ( 4 "context" 5 "database/sql" 6 7 "github.com/concourse/concourse/atc/db" 8 "github.com/concourse/concourse/atc/db/encryption" 9 "golang.org/x/crypto/acme/autocert" 10) 11 12type dbCache struct { 13 get, put, delete *sql.Stmt 14 es encryption.Strategy 15} 16 17func newDbCache(conn db.Conn) (autocert.Cache, error) { 18 c := new(dbCache) 19 c.es = conn.EncryptionStrategy() 20 var err error 21 c.get, err = conn.Prepare("SELECT cert, nonce FROM cert_cache WHERE domain = $1") 22 if err != nil { 23 return nil, err 24 } 25 c.put, err = conn.Prepare("INSERT INTO cert_cache (domain, cert, nonce) VALUES ($1, $2, $3) ON CONFLICT (domain) DO UPDATE SET domain = EXCLUDED.domain, cert = EXCLUDED.cert, nonce = EXCLUDED.nonce") 26 if err != nil { 27 return nil, err 28 } 29 c.delete, err = conn.Prepare("DELETE FROM cert_cache WHERE domain = $1") 30 return c, err 31} 32 33func (c *dbCache) Get(ctx context.Context, domain string) ([]byte, error) { 34 var ciphertext string 35 var nonce sql.NullString 36 err := c.get.QueryRowContext(ctx, domain).Scan(&ciphertext, &nonce) 37 if err == sql.ErrNoRows { 38 err = autocert.ErrCacheMiss 39 } 40 if err != nil { 41 return nil, err 42 } 43 var noncense *string 44 if nonce.Valid { 45 noncense = &nonce.String 46 } 47 return c.es.Decrypt(ciphertext, noncense) 48} 49 50func (c *dbCache) Put(ctx context.Context, domain string, cert []byte) error { 51 ciphertext, nonce, err := c.es.Encrypt(cert) 52 if err != nil { 53 return err 54 } 55 _, err = c.put.ExecContext(ctx, domain, ciphertext, nonce) 56 return err 57} 58 59func (c *dbCache) Delete(ctx context.Context, domain string) error { 60 _, err := c.delete.ExecContext(ctx, domain) 61 return err 62} 63