Skip to content

Commit

Permalink
feat(server): expose endpoint for certificates enumeration (j#IS-2824)
Browse files Browse the repository at this point in the history
  • Loading branch information
streambinder committed Jul 21, 2022
1 parent 26d7708 commit c43b530
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 19 deletions.
29 changes: 29 additions & 0 deletions server/enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package server

import (
"github.com/gofiber/fiber/v2"
"github.com/rs/zerolog/log"
"gitlab.rete.farm/sistemi/inca/pki"
)

func (inca *Inca) handlerEnum(c *fiber.Ctx) error {
filter := c.Params("filter", ".*")
results, err := (*inca.Cfg.Storage).Find(filter)
if err != nil {
log.Error().Err(err).Msg("unable to enumerate certificates")
return c.SendStatus(fiber.StatusInternalServerError)
}

crts := []Crt{}
for _, result := range results {
crt, err := pki.ParseBytes(result)
if err != nil {
log.Error().Err(err).Msg("unable to parse certificate")
}
crts = append(crts, EncodeCrt(crt))
}

return c.JSON(struct {
Results []Crt `json:"results"`
}{crts})
}
21 changes: 21 additions & 0 deletions server/inca.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package server

import (
"crypto/x509"
"os"
"time"

"github.com/gofiber/fiber/v2"
"github.com/rs/zerolog"
"gitlab.rete.farm/sistemi/inca/pki"
"gitlab.rete.farm/sistemi/inca/server/config"
"gitlab.rete.farm/sistemi/inca/server/middleware"
)
Expand All @@ -14,6 +17,23 @@ type Inca struct {
Cfg *config.Config
}

type Crt struct {
CN string `json:"name"`
AltNames []string `json:"alt"`
NotBefore time.Time `json:"not_before"`
NotAfter time.Time `json:"not_after"`
}

func EncodeCrt(crt *x509.Certificate) Crt {
dnsNames, ipAddresses := pki.AltNames(crt)
return Crt{
crt.Subject.CommonName,
append(dnsNames, ipAddresses...),
crt.NotBefore,
crt.NotAfter,
}
}

func Spinup(path string) (*Inca, error) {
cfg, err := config.Parse(path)
if err != nil {
Expand All @@ -22,6 +42,7 @@ func Spinup(path string) (*Inca, error) {

inca := &Inca{fiber.New(fiber.Config{DisableStartupMessage: true}), cfg}
inca.Use(middleware.Logger(zerolog.New(os.Stdout), func(c *fiber.Ctx) bool { return false }))
inca.Get("/", inca.handlerEnum)
inca.Get("/:name", inca.handlerCRT)
inca.Get("/:name/key", inca.handlerKey)
inca.Get("/:name/show", inca.handlerShow)
Expand Down
15 changes: 4 additions & 11 deletions server/show.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package server

import (
"time"

"github.com/gofiber/fiber/v2"
"github.com/rs/zerolog/log"
"gitlab.rete.farm/sistemi/inca/pki"
)

type Certificate struct {
}

func (inca *Inca) handlerShow(c *fiber.Ctx) error {
var name = c.Params("name")
if !pki.IsValidCN(name) {
Expand All @@ -26,13 +27,5 @@ func (inca *Inca) handlerShow(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusInternalServerError)
}

return c.JSON(struct {
Names []string `json:"names"`
NotBefore time.Time `json:"not_before"`
NotAfter time.Time `json:"not_after"`
}{
crt.DNSNames,
crt.NotBefore,
crt.NotAfter,
})
return c.JSON(EncodeCrt(crt))
}
1 change: 1 addition & 0 deletions storage/abstract.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Storage interface {
Put(name string, crtData *pem.Block, keyData *pem.Block) error
Get(name string) ([]byte, []byte, error)
Del(name string) error
Find(filters ...string) ([][]byte, error)
}

func Get(id string, options ...string) (*Storage, error) {
Expand Down
34 changes: 34 additions & 0 deletions storage/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,37 @@ func (s *FileSystem) Del(name string) error {

return os.RemoveAll(filepath.Join(s.path, name))
}

func (s *FileSystem) Find(filters ...string) ([][]byte, error) {
dirs, err := ioutil.ReadDir(s.path)
if err != nil {
return nil, err
}

results := [][]byte{}
for _, dir := range dirs {
if !dir.IsDir() {
continue
}

var (
crtPath = filepath.Join(s.path, dir.Name(), fsCrtName)
isResult = pki.IsValidCN(dir.Name()) && util.RegexesMatch(dir.Name(), filters...)
)

_, err := os.Stat(crtPath)
isResult = isResult && !os.IsNotExist(err)
if !isResult {
continue
}

crt, _, err := s.Get(dir.Name())
if err != nil {
return nil, err
}

results = append(results, crt)
}

return results, nil
}
50 changes: 42 additions & 8 deletions storage/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"gitlab.rete.farm/sistemi/inca/pki"
"gitlab.rete.farm/sistemi/inca/util"
)

var (
Expand Down Expand Up @@ -55,7 +56,7 @@ func (s *S3) Get(name string) ([]byte, []byte, error) {

crtData := bytes.NewBuffer(nil)
if data, err := client.GetObject(&s3.GetObjectInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
Key: &s3CrtName,
}); err != nil {
return nil, nil, err
Expand All @@ -68,7 +69,7 @@ func (s *S3) Get(name string) ([]byte, []byte, error) {

keyData := bytes.NewBuffer(nil)
if data, err := client.GetObject(&s3.GetObjectInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
Key: &s3KeyName,
}); err != nil {
return nil, nil, err
Expand All @@ -88,22 +89,22 @@ func (s *S3) Put(name string, crtData *pem.Block, keyData *pem.Block) error {
s.config,
)

if _, err := client.CreateBucket(&s3.CreateBucketInput{Bucket: bucket(name)}); err != nil &&
if _, err := client.CreateBucket(&s3.CreateBucketInput{Bucket: nameToBucket(name)}); err != nil &&
strings.HasPrefix(err.Error(), s3.ErrCodeBucketAlreadyExists) &&
strings.HasPrefix(err.Error(), s3.ErrCodeBucketAlreadyOwnedByYou) {
return err
}

if _, err := client.PutObject(&s3.PutObjectInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
Key: &s3CrtName,
Body: bytes.NewReader(pki.ExportBytes(crtData)),
}); err != nil {
return err
}

if _, err := client.PutObject(&s3.PutObjectInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
Key: &s3KeyName,
Body: bytes.NewReader(pki.ExportBytes(keyData)),
}); err != nil {
Expand All @@ -122,21 +123,54 @@ func (s *S3) Del(name string) error {
if err := s3manager.NewBatchDeleteWithClient(client).Delete(
aws.BackgroundContext(),
s3manager.NewDeleteListIterator(client, &s3.ListObjectsInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
})); err != nil {
return err
}

if _, err := client.DeleteBucket(&s3.DeleteBucketInput{
Bucket: bucket(name),
Bucket: nameToBucket(name),
}); err != nil {
return err
}

return nil
}

func bucket(name string) *string {
func (s *S3) Find(filters ...string) ([][]byte, error) {
client := s3.New(
session.Must(session.NewSession()),
s.config,
)

buckets, err := client.ListBuckets(&s3.ListBucketsInput{})
if err != nil {
return nil, err
}

results := [][]byte{}
for _, bucket := range buckets.Buckets {
if !(pki.IsValidCN(bucketToName(bucket.Name)) &&
util.RegexesMatch(bucketToName(bucket.Name), filters...)) {
continue
}

crt, _, err := s.Get(*bucket.Name)
if err != nil {
return nil, err
}

results = append(results, crt)
}

return results, nil
}

func nameToBucket(name string) *string {
bucket := strings.ReplaceAll(name, ".", "-")
return &bucket
}

func bucketToName(bucket *string) string {
return strings.ReplaceAll(*bucket, "-", ".")
}
11 changes: 11 additions & 0 deletions util/string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package util

import "regexp"

func RegexesMatch(payload string, regexes ...string) bool {
match := true
for _, filter := range regexes {
match = match && ErrWrap(false)(regexp.MatchString(filter, payload))
}
return match
}

0 comments on commit c43b530

Please sign in to comment.