certs

package module
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2025 License: Apache-2.0 Imports: 29 Imported by: 1

README

Abstract Machines Certificate Manager

codecov license

Abstract Machines Certicate Manager is an open source, lightweight, scalable, and customizable certs manager. This PKI (Public Key Infrastructure) service provides a comprehensive set of features for managing digital certificates. It includes an SDK, CLI, and API that enable the following functionality:

  • Certificate Issuance: Issue new certificates for entities, specifying parameters like the certificate type, TTL, IP addresses, and subject options.
  • Certificate Renewal: Renew existing certificates in the database.
  • Certificate Revocation: Revoke certificates that are no longer valid or trusted.
  • Certificate Retrieval: Retrieve certificate records from the database, including options to view, download, and get OCSP responses.
  • Certificate Listing: List certificates based on various filters, such as entity ID, expiry time, and revocation status.
  • Certificate Authority (CA) Management: Retrieve the chain of CA certificates (root and intermediate) and generate Certificate Revocation Lists (CRLs).

Features

  • PKI (Certicate renewal)
  • Active revocation (CRL, OSCP)
  • API (For management of PKI)
  • SDK
  • CLI

Prerequisites

The following are needed to run absmach certs:

Developing absmach certs will also require:

Install

Once the prerequisites are installed, clone the repo

git clone https://github.com/absmach/certs.git
cd certs

Execute the following commands from the project's root:

docker compose -f docker/docker-compose.yml --env-file docker/.env -p absmach up

This will bring up the certs docker services and interconnect them. This command can also be executed using the project's included Makefile:

make run

Usage

SDK

Absmach certs provides an SDK that can be imported and used in your Go applications. Here's an example of how to use the SDK:

cert , _ := sdk.IssueCert("entityID", "10h", []string{"ipAddr1", "ipAddr2"}, sdk.Options{CommonName: "commonName"})
fmt.Println(cert)
CLI

Absmach certs also provides a command-line interface (CLI) for interacting with the service. The CLI supports the following commands:

  • issue: Issue a new certificate
  • get: List certificates
  • token: Gets download token
  • download: Downloads a certificate
  • renew: Renew an existing certificate
  • revoke: Revoke a certificate
  • view: Retrieve a certificate
  • generate-crl: Generate a Certificate Revocation List (CRL)
  • token-ca: Gets CA download token
  • download-ca: Retrieve the chain of CA certificates
API

The absmach certs exposes a RESTful API that can be used to interact with the service programmatically. Here is an example using cURL:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"ip_addresses":["191.168.101.16"],"ttl":"10h","options":{"organization":["organization_name"]}}' \
  http://localhost:9010/certs/issue/64eeb24e-6154-48c4-ad32-e4fb02ed32da\?common_name\=thing

Contributing

Thank you for your interest in Absmach certs and the desire to contribute!

  1. Take a look at our open issues.
  2. Checkout the contribution guide to learn more about our style and conventions.
  3. Make your changes compatible to our workflow.

Also, explore our contrib repository for extra services such as Cassandra, InfluxDB, MongoDB readers and writers, LoRa, OPC UA support, Digital Twins, and more. If you have a contribution that is not a good fit for the core monorepo (it's specific to your use case, it's an additional feature or a new service, it's optional or an add-on), this is a great place to submit the pull request.

Community

License

Apache-2.0

Documentation

Index

Constants

View Source
const (
	Root    = "RootCA"
	Inter   = "IntermediateCA"
	Client  = "ClientCert"
	Unknown = "Unknown"
)
View Source
const (
	CertsService_GetEntityID_FullMethodName = "/absmach.certs.CertsService/GetEntityID"
	CertsService_RevokeCerts_FullMethodName = "/absmach.certs.CertsService/RevokeCerts"
)
View Source
const (
	Organization = "AbstractMacines"

	PrivateKeyBytes              = 2048
	RootCAValidityPeriod         = time.Hour * 24 * 365 // 365 days
	IntermediateCAVAlidityPeriod = time.Hour * 24 * 90  // 90 days

	PrivateKey      = "PRIVATE KEY"
	RSAPrivateKey   = "RSA PRIVATE KEY"
	ECPrivateKey    = "EC PRIVATE KEY"
	PKCS8PrivateKey = "PKCS8 PRIVATE KEY"
	EDPrivateKey    = "ED25519 PRIVATE KEY"
)

Variables

View Source
var (
	// Version represents the last service git tag in git history.
	// It's meant to be set using go build ldflags.
	Version = "0.0.0"

	Commit = "ffffffff"
	// BuildTime represetns the service build time.
	// It's meant to be set using go build ldflags.
	BuildTime = "1970-01-01_00:00:00"
)
View Source
var (
	ErrNotFound               = errors.New("entity not found")
	ErrConflict               = errors.New("entity already exists")
	ErrCreateEntity           = errors.New("failed to create entity")
	ErrViewEntity             = errors.New("view entity failed")
	ErrGetToken               = errors.New("failed to get token")
	ErrUpdateEntity           = errors.New("update entity failed")
	ErrMalformedEntity        = errors.New("malformed entity specification")
	ErrRootCANotFound         = errors.New("root CA not found")
	ErrIntermediateCANotFound = errors.New("intermediate CA not found")
	ErrCertExpired            = errors.New("certificate expired before renewal")
	ErrCertRevoked            = errors.New("certificate has been revoked and cannot be renewed")
	ErrCertInvalidType        = errors.New("invalid cert type")
	ErrInvalidLength          = errors.New("invalid length of serial numbers")
	ErrPrivKeyType            = errors.New("unsupported private key type")
	ErrPubKeyType             = errors.New("unsupported public key type")
	ErrFailedParse            = errors.New("failed to parse key PEM")
	ErrInvalidIP              = errors.New("invalid IP address")
)
View Source
var CertsService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "absmach.certs.CertsService",
	HandlerType: (*CertsServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "GetEntityID",
			Handler:    _CertsService_GetEntityID_Handler,
		},
		{
			MethodName: "RevokeCerts",
			Handler:    _CertsService_RevokeCerts_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "certs.proto",
}

CertsService_ServiceDesc is the grpc.ServiceDesc for CertsService service. It's only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)

View Source
var File_certs_proto protoreflect.FileDescriptor

Functions

func Health

func Health(service, instanceID string) http.HandlerFunc

Health exposes an HTTP handler for retrieving service health.

func RegisterCertsServiceServer

func RegisterCertsServiceServer(s grpc.ServiceRegistrar, srv CertsServiceServer)

Types

type CA

type CA struct {
	Type         CertType
	Certificate  *x509.Certificate
	PrivateKey   *rsa.PrivateKey
	SerialNumber string
}

type CAConfig

type CAConfig struct {
	CommonName         string   `yaml:"common_name"`
	Organization       []string `yaml:"organization"`
	OrganizationalUnit []string `yaml:"organizational_unit"`
	Country            []string `yaml:"country"`
	Province           []string `yaml:"province"`
	Locality           []string `yaml:"locality"`
	StreetAddress      []string `yaml:"street_address"`
	PostalCode         []string `yaml:"postal_code"`
	DNSNames           []string `yaml:"dns_names"`
	IPAddresses        []string `yaml:"ip_addresses"`
	ValidityPeriod     string   `yaml:"validity_period"`
}

type CSR

type CSR struct {
	CSR        []byte `json:"csr,omitempty"`
	PrivateKey []byte `json:"private_key,omitempty"`
}

type CSRMetadata

type CSRMetadata struct {
	CommonName         string           `json:"common_name"`
	Organization       []string         `json:"organization"`
	OrganizationalUnit []string         `json:"organizational_unit"`
	Country            []string         `json:"country"`
	Province           []string         `json:"province"`
	Locality           []string         `json:"locality"`
	StreetAddress      []string         `json:"street_address"`
	PostalCode         []string         `json:"postal_code"`
	DNSNames           []string         `json:"dns_names"`
	IPAddresses        []string         `json:"ip_addresses"`
	EmailAddresses     []string         `json:"email_addresses"`
	ExtraExtensions    []pkix.Extension `json:"extra_extensions"`
}

type CSRPage

type CSRPage struct {
	PageMetadata
	CSRs []CSR `json:"csrs,omitempty"`
}

type CertType

type CertType int
const (
	RootCA CertType = iota
	IntermediateCA
	ClientCert
)

func CertTypeFromString

func CertTypeFromString(s string) (CertType, error)

func (CertType) String

func (c CertType) String() string

type Certificate

type Certificate struct {
	SerialNumber string    `db:"serial_number"`
	Certificate  []byte    `db:"certificate"`
	Key          []byte    `db:"key"`
	Revoked      bool      `db:"revoked"`
	ExpiryTime   time.Time `db:"expiry_time"`
	EntityID     string    `db:"entity_id"`
	Type         CertType  `db:"type"`
	DownloadUrl  string    `db:"-"`
}

type CertificatePage

type CertificatePage struct {
	PageMetadata
	Certificates []Certificate
}

type CertsServiceClient

type CertsServiceClient interface {
	GetEntityID(ctx context.Context, in *EntityReq, opts ...grpc.CallOption) (*EntityRes, error)
	RevokeCerts(ctx context.Context, in *RevokeReq, opts ...grpc.CallOption) (*emptypb.Empty, error)
}

CertsServiceClient is the client API for CertsService service.

For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.

type CertsServiceServer

type CertsServiceServer interface {
	GetEntityID(context.Context, *EntityReq) (*EntityRes, error)
	RevokeCerts(context.Context, *RevokeReq) (*emptypb.Empty, error)
	// contains filtered or unexported methods
}

CertsServiceServer is the server API for CertsService service. All implementations must embed UnimplementedCertsServiceServer for forward compatibility.

type Config

type Config struct {
	CommonName         string   `yaml:"common_name"`
	Organization       []string `yaml:"organization"`
	OrganizationalUnit []string `yaml:"organizational_unit"`
	Country            []string `yaml:"country"`
	Province           []string `yaml:"province"`
	Locality           []string `yaml:"locality"`
	StreetAddress      []string `yaml:"street_address"`
	PostalCode         []string `yaml:"postal_code"`
	DNSNames           []string `yaml:"dns_names"`
	IPAddresses        []net.IP `yaml:"ip_addresses"`
	ValidityPeriod     string   `yaml:"validity_period"`
}

func LoadConfig

func LoadConfig(filename string) (*Config, error)

type EntityReq

type EntityReq struct {
	SerialNumber string `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
	// contains filtered or unexported fields
}

func (*EntityReq) Descriptor deprecated

func (*EntityReq) Descriptor() ([]byte, []int)

Deprecated: Use EntityReq.ProtoReflect.Descriptor instead.

func (*EntityReq) GetSerialNumber

func (x *EntityReq) GetSerialNumber() string

func (*EntityReq) ProtoMessage

func (*EntityReq) ProtoMessage()

func (*EntityReq) ProtoReflect

func (x *EntityReq) ProtoReflect() protoreflect.Message

func (*EntityReq) Reset

func (x *EntityReq) Reset()

func (*EntityReq) String

func (x *EntityReq) String() string

type EntityRes

type EntityRes struct {
	EntityId string `protobuf:"bytes,1,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"`
	// contains filtered or unexported fields
}

func (*EntityRes) Descriptor deprecated

func (*EntityRes) Descriptor() ([]byte, []int)

Deprecated: Use EntityRes.ProtoReflect.Descriptor instead.

func (*EntityRes) GetEntityId

func (x *EntityRes) GetEntityId() string

func (*EntityRes) ProtoMessage

func (*EntityRes) ProtoMessage()

func (*EntityRes) ProtoReflect

func (x *EntityRes) ProtoReflect() protoreflect.Message

func (*EntityRes) Reset

func (x *EntityRes) Reset()

func (*EntityRes) String

func (x *EntityRes) String() string

type HealthInfo

type HealthInfo struct {
	// Status contains service status.
	Status string `json:"status"`

	// Version contains current service version.
	Version string `json:"version"`

	// Commit represents the git hash commit.
	Commit string `json:"commit"`

	// Description contains service description.
	Description string `json:"description"`

	// BuildTime contains service build time.
	BuildTime string `json:"build_time"`

	// InstanceID contains the ID of the current service instance
	InstanceID string `json:"instance_id"`
}

HealthInfo contains version endpoint response.

type PageMetadata

type PageMetadata struct {
	Total    uint64 `json:"total" db:"total"`
	Offset   uint64 `json:"offset,omitempty" db:"offset"`
	Limit    uint64 `json:"limit" db:"limit"`
	EntityID string `json:"entity_id,omitempty" db:"entity_id"`
}

type Repository

type Repository interface {
	// CreateCert adds a certificate record to the database.
	CreateCert(ctx context.Context, cert Certificate) error

	// RetrieveCert retrieves a certificate record from the database.
	RetrieveCert(ctx context.Context, serialNumber string) (Certificate, error)

	// UpdateCert updates a certificate record in the database.
	UpdateCert(ctx context.Context, cert Certificate) error

	// ListCerts retrieves the certificates from the database while applying filters.
	ListCerts(ctx context.Context, pm PageMetadata) (CertificatePage, error)

	// GetCAs retrieves rootCA and intermediateCA from database.
	GetCAs(ctx context.Context, caType ...CertType) ([]Certificate, error)

	// ListRevokedCerts retrieves revoked lists from database.
	ListRevokedCerts(ctx context.Context) ([]Certificate, error)

	// RemoveCert deletes cert from database.
	RemoveCert(ctx context.Context, entityId string) error

	// RevokeCertsByEntityID revokes all certificates for a given entity ID.
	RevokeCertsByEntityID(ctx context.Context, entityID string) error
}

type RevokeReq

type RevokeReq struct {
	EntityId string `protobuf:"bytes,1,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"`
	// contains filtered or unexported fields
}

func (*RevokeReq) Descriptor deprecated

func (*RevokeReq) Descriptor() ([]byte, []int)

Deprecated: Use RevokeReq.ProtoReflect.Descriptor instead.

func (*RevokeReq) GetEntityId

func (x *RevokeReq) GetEntityId() string

func (*RevokeReq) ProtoMessage

func (*RevokeReq) ProtoMessage()

func (*RevokeReq) ProtoReflect

func (x *RevokeReq) ProtoReflect() protoreflect.Message

func (*RevokeReq) Reset

func (x *RevokeReq) Reset()

func (*RevokeReq) String

func (x *RevokeReq) String() string

type Service

type Service interface {
	// RenewCert renews a certificate from the database.
	RenewCert(ctx context.Context, serialNumber string) error

	// RevokeCert revokes a certificate from the database.
	RevokeCert(ctx context.Context, serialNumber string) error

	// RetrieveCert retrieves a certificate record from the database.
	RetrieveCert(ctx context.Context, token, serialNumber string) (Certificate, []byte, error)

	// ViewCert retrieves a certificate record from the database.
	ViewCert(ctx context.Context, serialNumber string) (Certificate, error)

	// ListCerts retrieves the certificates from the database while applying filters.
	ListCerts(ctx context.Context, pm PageMetadata) (CertificatePage, error)

	// RetrieveCertDownloadToken generates a certificate download token.
	// The token is needed to download the client certificate.
	RetrieveCertDownloadToken(ctx context.Context, serialNumber string) (string, error)

	// RetrieveCAToken generates a CA download and view token.
	// The token is needed to view and download the CA certificate.
	RetrieveCAToken(ctx context.Context) (string, error)

	// IssueCert issues a certificate from the database.
	IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions) (Certificate, error)

	// OCSP retrieves the OCSP response for a certificate.
	OCSP(ctx context.Context, serialNumber string) (*Certificate, int, *x509.Certificate, error)

	// GetEntityID retrieves the entity ID for a certificate.
	GetEntityID(ctx context.Context, serialNumber string) (string, error)

	// GenerateCRL creates cert revocation list.
	GenerateCRL(ctx context.Context, caType CertType) ([]byte, error)

	// GetChainCA retrieves the chain of CA i.e. root and intermediate cert concat together.
	GetChainCA(ctx context.Context, token string) (Certificate, error)

	// RemoveCert deletes a cert for a provided  entityID.
	RemoveCert(ctx context.Context, entityId string) error

	// IssueFromCSR creates a certificate from a given CSR.
	IssueFromCSR(ctx context.Context, entityID, ttl string, csr CSR) (Certificate, error)

	// RevokeCerts revokes all certificates for a given entity ID.
	RevokeCerts(ctx context.Context, entityID string) error
}

func NewService

func NewService(ctx context.Context, repo Repository, config *Config) (Service, error)

type SubjectOptions

type SubjectOptions struct {
	CommonName         string
	Organization       []string `json:"organization"`
	OrganizationalUnit []string `json:"organizational_unit"`
	Country            []string `json:"country"`
	Province           []string `json:"province"`
	Locality           []string `json:"locality"`
	StreetAddress      []string `json:"street_address"`
	PostalCode         []string `json:"postal_code"`
	DnsNames           []string `json:"dns_names"`
	IpAddresses        []net.IP `json:"ip_addresses"`
}

type UnimplementedCertsServiceServer

type UnimplementedCertsServiceServer struct{}

UnimplementedCertsServiceServer must be embedded to have forward compatible implementations.

NOTE: this should be embedded by value instead of pointer to avoid a nil pointer dereference when methods are called.

func (UnimplementedCertsServiceServer) GetEntityID

func (UnimplementedCertsServiceServer) RevokeCerts

type UnsafeCertsServiceServer

type UnsafeCertsServiceServer interface {
	// contains filtered or unexported methods
}

UnsafeCertsServiceServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to CertsServiceServer will result in compilation errors.

Directories

Path Synopsis
api
cmd
certs command
cli command
Package main contains cli main function to run the cli.
Package main contains cli main function to run the cli.
postgres
sdk

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL