NOISSUE - Update cocos to match certs changes (#520)
CI / checkproto (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled

* pass domain id to agent environment

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* update generated files

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* use certs sdk directly

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* remove redundant variables

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* use agent certs token for csr

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* update certs and add token to create req

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* fix atls

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* add agent token to certificate provider

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* pass certs token to agent

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* use sdk for csr

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* update atls

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* fix tests

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* address comments

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* remove unused structs

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* update tests

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* lint

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* fix tests

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* lint

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* remove unused domain id

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* refactor tests and remove unused struct fields

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* refactor(atls): remove CAClient and inline CA certificate issuance

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* lint'

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* increase coverage

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* fix bug in certs sdk and certificate provider

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* update certs

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

* fix pkg stress

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>

---------

Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
This commit is contained in:
Washington Kigani Kamadi
2025-10-06 22:12:18 +03:00
committed by GitHub
parent 0be724386b
commit 0ffc2d17cf
12 changed files with 441 additions and 261 deletions
+18 -10
View File
@@ -6,16 +6,24 @@ Agent service provides a barebones HTTP and gRPC API and Service interface imple
The service is configured using the environment variables from the following table. Note that any unset variables will be replaced with their default values.
| Variable | Description | Default |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| AGENT_LOG_LEVEL | Log level for agent service (debug, info, warn, error) | debug |
| AGENT_CVM_GRPC_HOST | Agent service gRPC host | "" |
| AGENT_CVM_GRPC_PORT | Agent service gRPC port | 7001 |
| AGENT_CVM_GRPC_SERVER_CERT | Path to gRPC server certificate in pem format | "" |
| AGENT_CVM_GRPC_SERVER_KEY | Path to gRPC server key in pem format | "" |
| AGENT_CVM_GRPC_SERVER_CA_CERTS | Path to gRPC server CA certificate | "" |
| AGENT_CVM_GRPC_CLIENT_CA_CERTS | Path to gRPC client CA certificate | "" |
| AGENT_CVM_CA_URL | URL for CA service, if provided it will be used for certificate generation, used only with aTLS at the moment | "" |
| Variable | Description | Default |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| AGENT_LOG_LEVEL | Log level for agent service (debug, info, warn, error) | debug |
| AGENT_VMPL | VMPL (Virtual Machine Privilege Level) for AMD SEV-SNP attestation (0-3) | 2 |
| AGENT_GRPC_HOST | Agent service gRPC host address | 0.0.0.0 |
| AGENT_CVM_GRPC_HOST | Agent service gRPC host | "" |
| AGENT_CVM_GRPC_PORT | Agent service gRPC port | 7001 |
| AGENT_CVM_GRPC_SERVER_CERT | Path to gRPC server certificate in pem format | "" |
| AGENT_CVM_GRPC_SERVER_KEY | Path to gRPC server key in pem format | "" |
| AGENT_CVM_GRPC_SERVER_CA_CERTS | Path to gRPC server CA certificate | "" |
| AGENT_CVM_GRPC_CLIENT_CA_CERTS | Path to gRPC client CA certificate | "" |
| AGENT_CVM_CA_URL | URL for CA service, if provided it will be used for certificate generation, used only with aTLS at the moment | "" |
| AGENT_CVM_ID | Unique identifier for the CVM (Confidential Virtual Machine) | "" |
| AGENT_CERTS_TOKEN | Authentication token for certificate service access | "" |
| AGENT_MAA_URL | Microsoft Azure Attestation service URL for Azure attestation | https://sharedeus2.eus2.attest.azure.net |
| AGENT_OS_BUILD | Operating system build information for attestation | UVC |
| AGENT_OS_DISTRO | Operating system distribution information for attestation | UVC |
| AGENT_OS_TYPE | Operating system type information for attestation | UVC |
## Deployment
+18 -13
View File
@@ -14,8 +14,8 @@ import (
"os"
"os/signal"
"syscall"
"time"
"github.com/absmach/certs/sdk"
mglog "github.com/absmach/supermq/logger"
"github.com/absmach/supermq/pkg/prometheus"
"github.com/caarlos0/env/v11"
@@ -39,22 +39,21 @@ import (
const (
svcName = "agent"
defSvcGRPCPort = "7002"
retryInterval = 5 * time.Second
envPrefixCVMGRPC = "AGENT_CVM_GRPC_"
storageDir = "/var/lib/cocos/agent"
)
type config struct {
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
AgentGrpcHost string `env:"AGENT_GRPC_HOST" envDefault:"0.0.0.0"`
CAUrl string `env:"AGENT_CVM_CA_URL" envDefault:""`
CVMId string `env:"AGENT_CVM_ID" envDefault:""`
AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"`
AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"`
AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"`
AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"`
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
AgentGrpcHost string `env:"AGENT_GRPC_HOST" envDefault:"0.0.0.0"`
CAUrl string `env:"AGENT_CVM_CA_URL" envDefault:""`
CVMId string `env:"AGENT_CVM_ID" envDefault:""`
CertsToken string `env:"AGENT_CERTS_TOKEN" envDefault:""`
AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"`
AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"`
AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"`
AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"`
}
func main() {
@@ -167,7 +166,13 @@ func main() {
var certProvider atls.CertificateProvider
if ccPlatform != attestation.NoCC {
certProvider, err = atls.NewProvider(provider, ccPlatform, cfg.CVMId, cfg.CAUrl)
var certsSDK sdk.SDK
if cfg.CAUrl != "" {
certsSDK = sdk.NewSDK(sdk.Config{
CertsURL: cfg.CAUrl,
})
}
certProvider, err = atls.NewProvider(provider, ccPlatform, cfg.CertsToken, cfg.CVMId, certsSDK)
if err != nil {
logger.Error(fmt.Sprintf("failed to create certificate provider: %s", err))
exitCode = 1
+5 -6
View File
@@ -35,12 +35,11 @@ import (
)
const (
svcName = "manager"
envPrefixGRPC = "MANAGER_GRPC_"
envPrefixHTTP = "MANAGER_HTTP_"
envPrefixQemu = "MANAGER_QEMU_"
clientBufferSize = 100
defSvcHTTPPort = "7003"
svcName = "manager"
envPrefixGRPC = "MANAGER_GRPC_"
envPrefixHTTP = "MANAGER_HTTP_"
envPrefixQemu = "MANAGER_QEMU_"
defSvcHTTPPort = "7003"
)
type config struct {
+9 -11
View File
@@ -15,10 +15,10 @@ require (
github.com/virtee/sev-snp-measure-go v0.0.0-20240530153610-e6e8dc9b6877
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0
go.opentelemetry.io/otel/trace v1.38.0
golang.org/x/crypto v0.41.0
golang.org/x/sync v0.16.0
google.golang.org/grpc v1.75.0
google.golang.org/protobuf v1.36.8
golang.org/x/crypto v0.42.0
golang.org/x/sync v0.17.0
google.golang.org/grpc v1.75.1
google.golang.org/protobuf v1.36.9
)
require (
@@ -63,7 +63,6 @@ require (
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
@@ -72,7 +71,6 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587 // indirect
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
github.com/zeebo/errs v1.4.0 // indirect
@@ -84,18 +82,18 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/time v0.12.0 // indirect
google.golang.org/api v0.247.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.5.1 // indirect
moul.io/http2curl v1.0.0 // indirect
)
require (
github.com/absmach/certs v0.17.0
github.com/absmach/certs v0.17.1-0.20251006092614-ffc1e886a28a
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -114,9 +112,9 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.0
github.com/prometheus/client_golang v1.23.2
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
@@ -125,7 +123,7 @@ require (
golang.org/x/net v0.43.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0
golang.org/x/text v0.28.0 // indirect
golang.org/x/text v0.29.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+60 -22
View File
@@ -34,8 +34,10 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/absmach/certs v0.17.0 h1:b2PrRUzDTeVUznbWVTg2xCZeCKTIqx+W/qnEOzkNXPA=
github.com/absmach/certs v0.17.0/go.mod h1:B+qydTGoBxyGR7FTpuCT9CreppNmpaGP68AJvinXDgE=
github.com/absmach/certs v0.17.1-0.20251006092614-ffc1e886a28a h1:894h9JmlnXp4/Qzpkauk/bd/6QapxXdBcc8i+88Sf1Q=
github.com/absmach/certs v0.17.1-0.20251006092614-ffc1e886a28a/go.mod h1:m6CWmAio930laR1TLZ3HhQna4f9KmSyyUGfD8EFZHwE=
github.com/absmach/senml v1.0.8 h1:+opem/r4g6c6eA/JLyCIuksyEhj7eBdysY3pEmy1mqo=
github.com/absmach/senml v1.0.8/go.mod h1:DRhzHLgvQoIUHroBgpFrSWso+bJZO9E96RlHAHy+VRI=
github.com/absmach/supermq v0.18.1 h1:JRLP6rfSzZoHgRGPfwNSmzJ7a4K4b4Dvz2nCmR32rxI=
github.com/absmach/supermq v0.18.1/go.mod h1:dYnFOIcGQzZ1WpYt1qNv1g609WmOWYzWCBBRjPQV7Uk=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -62,6 +64,10 @@ github.com/danko-miladinovic/go-tpm-tools v0.0.0-20250228160324-1ebcfd79567c/go.
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgraph-io/ristretto/v2 v2.3.0 h1:qTQ38m7oIyd4GAed/QkUZyPFNMnvVWyazGXRwvOt5zk=
github.com/dgraph-io/ristretto/v2 v2.3.0/go.mod h1:gpoRV3VzrEY1a9dWAYV6T1U7YzfgttXdd/ZzL1s9OZM=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
@@ -70,6 +76,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff h1:V6A5kD0+c1Qg4X72Lg+zxhCZk+par436sQdgLvMCBBc=
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff/go.mod h1:Lz4QaomI4wU2YbatD4/W7vatW2Q35tnkoJezB1clscc=
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
@@ -84,8 +92,12 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
@@ -101,6 +113,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0=
@@ -147,10 +161,18 @@ github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25d
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
@@ -161,6 +183,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs=
github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k=
github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVfecA=
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -181,8 +215,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587 h1:xzZOeCMQLA/W198ZkdVdt4EKFKJtS26B773zNU377ZY=
@@ -190,19 +222,23 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587/go.mod h1
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rubenv/sql-migrate v1.8.0 h1:dXnYiJk9k3wetp7GfQbKJcPHjVJL6YK19tKj8t2Ns0o=
github.com/rubenv/sql-migrate v1.8.0/go.mod h1:F2bGFBwCU+pnmbtNYDeKvSuvL6lBVtXDXUUv5t+u1qw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sammyoina/sev-snp-measure-go v0.0.0-20241202151803-ef189f0ff825 h1:SqNaL9udBIc026SGNEuEuiVL0/hw9fXxM5qrFhWGkdE=
github.com/sammyoina/sev-snp-measure-go v0.0.0-20241202151803-ef189f0ff825/go.mod h1:dEkBe8JnxU5itNjZDEQINFd7f7l4DtjfqRuzPQcit4w=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smarty/assertions v1.16.0 h1:EvHNkdRA4QHMrn75NZSoUQ/mAUXAYWfatfB01yTCzfY=
@@ -221,6 +257,8 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
@@ -254,11 +292,13 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4=
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -275,8 +315,8 @@ golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKl
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -302,8 +342,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -321,15 +361,13 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+11 -2
View File
@@ -34,6 +34,7 @@ type CreateReq struct {
AgentCvmServerUrl string `protobuf:"bytes,5,opt,name=agent_cvm_server_url,json=agentCvmServerUrl,proto3" json:"agent_cvm_server_url,omitempty"`
AgentCvmCaUrl string `protobuf:"bytes,6,opt,name=agent_cvm_ca_url,json=agentCvmCaUrl,proto3" json:"agent_cvm_ca_url,omitempty"`
Ttl string `protobuf:"bytes,7,opt,name=ttl,proto3" json:"ttl,omitempty"`
AgentCertsToken string `protobuf:"bytes,8,opt,name=agent_certs_token,json=agentCertsToken,proto3" json:"agent_certs_token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -117,6 +118,13 @@ func (x *CreateReq) GetTtl() string {
return ""
}
func (x *CreateReq) GetAgentCertsToken() string {
if x != nil {
return x.AgentCertsToken
}
return ""
}
type CreateRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
ForwardedPort string `protobuf:"bytes,1,opt,name=forwarded_port,json=forwardedPort,proto3" json:"forwarded_port,omitempty"`
@@ -441,7 +449,7 @@ var File_manager_manager_proto protoreflect.FileDescriptor
const file_manager_manager_proto_rawDesc = "" +
"\n" +
"\x15manager/manager.proto\x12\amanager\x1a\x1bgoogle/protobuf/empty.proto\"\xbb\x02\n" +
"\x15manager/manager.proto\x12\amanager\x1a\x1bgoogle/protobuf/empty.proto\"\xe7\x02\n" +
"\tCreateReq\x12&\n" +
"\x0fagent_log_level\x18\x01 \x01(\tR\ragentLogLevel\x126\n" +
"\x18agent_cvm_server_ca_cert\x18\x02 \x01(\fR\x14agentCvmServerCaCert\x12/\n" +
@@ -449,7 +457,8 @@ const file_manager_manager_proto_rawDesc = "" +
"\x15agent_cvm_client_cert\x18\x04 \x01(\fR\x12agentCvmClientCert\x12/\n" +
"\x14agent_cvm_server_url\x18\x05 \x01(\tR\x11agentCvmServerUrl\x12'\n" +
"\x10agent_cvm_ca_url\x18\x06 \x01(\tR\ragentCvmCaUrl\x12\x10\n" +
"\x03ttl\x18\a \x01(\tR\x03ttl\"I\n" +
"\x03ttl\x18\a \x01(\tR\x03ttl\x12*\n" +
"\x11agent_certs_token\x18\b \x01(\tR\x0fagentCertsToken\"I\n" +
"\tCreateRes\x12%\n" +
"\x0eforwarded_port\x18\x01 \x01(\tR\rforwardedPort\x12\x15\n" +
"\x06cvm_id\x18\x02 \x01(\tR\x05cvmId\"\"\n" +
+1
View File
@@ -24,6 +24,7 @@ message CreateReq{
string agent_cvm_server_url = 5;
string agent_cvm_ca_url = 6;
string ttl = 7;
string agent_certs_token = 8;
}
message CreateRes{
+2 -1
View File
@@ -27,7 +27,6 @@ import (
)
const (
hashLength = 32
persistenceDir = "/tmp/cocos"
agentLogLevelKey = "AGENT_LOG_LEVEL"
agentCvmGrpcUrlKey = "AGENT_CVM_GRPC_URL"
@@ -35,6 +34,7 @@ const (
agentCvmClientKey = "AGENT_CVM_GRPC_CLIENT_KEY"
agentCvmServerCaCertKey = "AGENT_CVM_GRPC_SERVER_CA_CERTS"
agentCvmId = "AGENT_CVM_ID"
agentCaToken = "AGENT_CERTS_TOKEN"
agentCvmCaUrl = "AGENT_CVM_CA_URL"
defClientCertPath = "/etc/certs/cert.pem"
defClientKeyPath = "/etc/certs/key.pem"
@@ -446,6 +446,7 @@ func tmpEnvironment(id string, req *CreateReq) (string, error) {
agentLogLevelKey: req.AgentLogLevel,
agentCvmGrpcUrlKey: req.AgentCvmServerUrl,
agentCvmId: id,
agentCaToken: req.AgentCertsToken,
agentCvmCaUrl: req.AgentCvmCaUrl,
}
+2 -101
View File
@@ -3,23 +3,9 @@
package atls
import (
"bytes"
"crypto/ecdsa"
"encoding/asn1"
"encoding/hex"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/absmach/certs"
certscli "github.com/absmach/certs/cli"
"github.com/absmach/certs/errors"
certssdk "github.com/absmach/certs/sdk"
)
const (
@@ -38,6 +24,7 @@ var (
// CertificateSubject contains certificate subject information.
type CertificateSubject struct {
Organization string
CommonName string
Country string
Province string
Locality string
@@ -49,6 +36,7 @@ type CertificateSubject struct {
func DefaultCertificateSubject() CertificateSubject {
return CertificateSubject{
Organization: "Ultraviolet",
CommonName: "Ultraviolet",
Country: "Serbia",
Province: "",
Locality: "Belgrade",
@@ -57,93 +45,6 @@ func DefaultCertificateSubject() CertificateSubject {
}
}
// CAClient handles communication with Certificate Authority.
type CAClient struct {
baseURL string
client *http.Client
}
type CSRRequest struct {
CSR string `json:"csr,omitempty"`
}
func NewCAClient(baseURL string) *CAClient {
return &CAClient{
baseURL: baseURL,
client: &http.Client{},
}
}
func (c *CAClient) RequestCertificate(csrMetadata certs.CSRMetadata, privateKey *ecdsa.PrivateKey, cvmID string, ttl time.Duration) ([]byte, error) {
csr, sdkerr := certscli.CreateCSR(csrMetadata, privateKey)
if sdkerr != nil {
return nil, fmt.Errorf("failed to create CSR: %w", sdkerr)
}
request := CSRRequest{CSR: string(csr.CSR)}
requestData, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("failed to marshal CSR request: %w", err)
}
endpoint := fmt.Sprintf("certs/csrs/%s", cvmID)
query := url.Values{}
query.Add("ttl", ttl.String())
requestURL := fmt.Sprintf("%s/%s?%s", c.baseURL, endpoint, query.Encode())
_, responseBody, err := c.processRequest(http.MethodPost, requestURL, requestData, nil, http.StatusOK)
if err != nil {
return nil, fmt.Errorf("failed to process CA request: %w", err)
}
var cert certssdk.Certificate
if err := json.Unmarshal(responseBody, &cert); err != nil {
return nil, fmt.Errorf("failed to unmarshal certificate response: %w", err)
}
cleanCertificateString := strings.ReplaceAll(cert.Certificate, "\\n", "\n")
block, rest := pem.Decode([]byte(cleanCertificateString))
if len(rest) != 0 {
return nil, fmt.Errorf("failed to decode certificate PEM: unexpected remaining data")
}
if block == nil {
return nil, fmt.Errorf("failed to decode certificate PEM: no PEM block found")
}
return block.Bytes, nil
}
func (c *CAClient) processRequest(method, reqURL string, data []byte, headers map[string]string, expectedRespCodes ...int) (http.Header, []byte, errors.SDKError) {
req, err := http.NewRequest(method, reqURL, bytes.NewReader(data))
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
req.Header.Add("Content-Type", "application/json")
for key, value := range headers {
req.Header.Add(key, value)
}
resp, err := c.client.Do(req)
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
defer resp.Body.Close()
sdkErr := errors.CheckError(resp, expectedRespCodes...)
if sdkErr != nil {
return make(http.Header), []byte{}, sdkErr
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return make(http.Header), []byte{}, errors.NewSDKError(err)
}
return resp.Header, body, nil
}
func extractNonceFromSNI(serverName string) ([]byte, error) {
if len(serverName) < len(nonceSuffix) || !hasNonceSuffix(serverName) {
return nil, fmt.Errorf("invalid server name: %s", serverName)
+281 -87
View File
@@ -12,19 +12,18 @@ import (
"crypto/x509/pkix"
"encoding/asn1"
"encoding/hex"
"encoding/json"
"encoding/pem"
"fmt"
"math/big"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/absmach/certs"
certssdk "github.com/absmach/certs/sdk"
sdkmocks "github.com/absmach/certs/sdk/mocks"
"github.com/absmach/supermq/pkg/errors"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/proto/check"
@@ -39,10 +38,70 @@ import (
"google.golang.org/protobuf/encoding/protojson"
)
const sevProductNameMilan = "Milan"
const (
sevProductNameMilan = "Milan"
)
var policy = attestation.Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &attestation.PcrConfig{}}
func generateTestCertPEM(t *testing.T) string {
return generateTestCertPEMWithSubject(t, "test")
}
func generateTestCertPEMWithSubject(t *testing.T, commonName string) string {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: commonName,
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
require.NoError(t, err)
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: certDER,
})
return strings.ReplaceAll(string(certPEM), "\n", "\\n")
}
func generateTestCertificateWithExtensions(t *testing.T, extensions []pkix.Extension) *x509.Certificate {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "test",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
ExtraExtensions: extensions,
}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
require.NoError(t, err)
cert, err := x509.ParseCertificate(certDER)
require.NoError(t, err)
return cert
}
// TestCertificateSubject tests the CertificateSubject functionality.
func TestDefaultCertificateSubject(t *testing.T) {
subject := DefaultCertificateSubject()
@@ -58,15 +117,15 @@ func TestDefaultCertificateSubject(t *testing.T) {
// TestUnifiedCertificateGenerator tests the unified certificate generator.
func TestUnifiedCertificateGenerator(t *testing.T) {
t.Run("SelfSignedGenerator", func(t *testing.T) {
generator, err := NewProvider(nil, attestation.SNPvTPM, "", "")
generator, err := NewProvider(nil, attestation.SNPvTPM, "", "", nil)
assert.NoError(t, err)
assert.NotNil(t, generator)
})
t.Run("CASignedGenerator", func(t *testing.T) {
caURL := "https://example.com/ca"
cvmID := "test-cvm-id"
generator, err := NewProvider(nil, attestation.SNPvTPM, caURL, cvmID)
mockSDK := sdkmocks.NewSDK(t)
generator, err := NewProvider(nil, attestation.SNPvTPM, "test-token", "test-cvm-id", mockSDK)
assert.NoError(t, err)
assert.NotNil(t, generator)
})
@@ -204,19 +263,27 @@ func TestNewProvider(t *testing.T) {
mockProvider := new(mocks.Provider)
t.Run("SelfSignedProvider", func(t *testing.T) {
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "")
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "", nil)
assert.NoError(t, err)
assert.NotNil(t, provider)
})
t.Run("CASignedProvider", func(t *testing.T) {
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "https://example.com", "test-cvm")
t.Run("CASignedProviderWithSDK", func(t *testing.T) {
mockSDK := sdkmocks.NewSDK(t)
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "test-token", "test-cvm-id", mockSDK)
assert.NoError(t, err)
assert.NotNil(t, provider)
})
t.Run("SelfSignedProviderNilSDK", func(t *testing.T) {
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "test-token", "test-cvm-id", nil)
assert.NoError(t, err)
assert.NotNil(t, provider)
})
t.Run("InvalidPlatformType", func(t *testing.T) {
_, err := NewProvider(mockProvider, attestation.PlatformType(999), "", "")
_, err := NewProvider(mockProvider, attestation.PlatformType(999), "", "", nil)
assert.Error(t, err)
})
}
@@ -514,47 +581,6 @@ func TestVerifyCertificateExtension(t *testing.T) {
// Helper functions
func createMockCAServer(t *testing.T) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
// Create a valid test certificate
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Organization: []string{"Test CA"},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
}
certDER, err := x509.CreateCertificate(rand.Reader, template, template, &privKey.PublicKey, privKey)
require.NoError(t, err)
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: certDER,
})
mockCert := certssdk.Certificate{
Certificate: string(certPEM),
}
response, _ := json.Marshal(mockCert)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write(response)
}))
}
func prepVerifyAttReport(t *testing.T) *sevsnp.Attestation {
file, err := os.ReadFile("../../attestation.bin")
require.NoError(t, err)
@@ -686,40 +712,199 @@ func TestCertificateVerification(t *testing.T) {
})
}
// TestProcessRequestEdgeCases tests CAClient.processRequest edge cases.
func TestProcessRequestEdgeCases(t *testing.T) {
client := NewCAClient("http://example.com")
// TestAttestedCAProvider tests the CA-signed certificate provider.
func TestAttestedCAProvider(t *testing.T) {
mockProvider := new(mocks.Provider)
attestationProvider, err := NewAttestationProvider(mockProvider, attestation.SNPvTPM)
require.NoError(t, err)
t.Run("InvalidURL", func(t *testing.T) {
_, _, err := client.processRequest("GET", "://invalid-url", nil, nil, http.StatusOK)
assert.Error(t, err)
subject := DefaultCertificateSubject()
cvmID := "test-cvm-id"
agentToken := "test-token"
t.Run("NewAttestedCAProvider", func(t *testing.T) {
provider := NewAttestedCAProvider(attestationProvider, subject, nil, cvmID, agentToken)
assert.NotNil(t, provider)
})
t.Run("NetworkError", func(t *testing.T) {
_, _, err := client.processRequest("GET", "http://nonexistent-domain-12345.com", nil, nil, http.StatusOK)
t.Run("SetTTL", func(t *testing.T) {
provider := NewAttestedCAProvider(attestationProvider, subject, nil, cvmID, agentToken)
newTTL := time.Hour * 48
provider.(*attestedCertificateProvider).SetTTL(newTTL)
attestedProvider := provider.(*attestedCertificateProvider)
assert.Equal(t, newTTL, attestedProvider.ttl)
})
}
// TestCASignedCertificateErrors tests error cases in CA-signed certificate generation.
func TestCASignedCertificateErrors(t *testing.T) {
mockProvider := new(mocks.Provider)
attestationProvider, err := NewAttestationProvider(mockProvider, attestation.SNPvTPM)
require.NoError(t, err)
subject := DefaultCertificateSubject()
cvmID := "test-cvm-id"
agentToken := "test-token"
cases := []struct {
name string
certificate string
sdkError error
expectedError string
}{
{"SDKIssueError", "", errors.NewSDKError(errors.New("SDK error")), "SDK error"},
{"InvalidPEMWithRemainingData", "-----BEGIN CERTIFICATE-----\\nVGVzdA==\\n-----END CERTIFICATE-----\\nExtra data here", nil, "unexpected remaining data"},
{"NoPEMBlockFound", "", nil, "no PEM block found"},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
mockSDK := sdkmocks.NewSDK(t)
expectedCSR := certs.CSR{CSR: []byte("test-csr")}
mockSDK.On("CreateCSR", mock.Anything, mock.Anything).Return(expectedCSR, errors.SDKError(nil))
mockSDK.On("IssueFromCSRInternal", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(certssdk.Certificate{Certificate: c.certificate}, c.sdkError)
provider := NewAttestedCAProvider(attestationProvider, subject, mockSDK, cvmID, agentToken)
attestedProvider := provider.(*attestedCertificateProvider)
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
extension := pkix.Extension{
Id: SNPvTPMOID,
Value: []byte("test-data"),
}
_, err = attestedProvider.generateCASignedCertificate(privateKey, extension)
assert.Error(t, err)
assert.Contains(t, err.Error(), c.expectedError)
})
}
}
// TestGetCertificateErrors tests error paths in certificate generation.
func TestGetCertificateErrors(t *testing.T) {
t.Run("InvalidServerNameFormat", func(t *testing.T) {
mockProvider := new(mocks.Provider)
attestationProvider, err := NewAttestationProvider(mockProvider, attestation.SNPvTPM)
require.NoError(t, err)
provider := NewAttestedProvider(attestationProvider, DefaultCertificateSubject())
clientHello := &tls.ClientHelloInfo{
ServerName: "invalid-format",
}
_, err = provider.GetCertificate(clientHello)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to extract nonce")
})
t.Run("CustomHeaders", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "test-value", r.Header.Get("Custom-Header"))
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
t.Run("AttestationProviderError", func(t *testing.T) {
mockProvider := new(mocks.Provider)
mockProvider.On("Attestation", mock.Anything, mock.Anything).Return(nil, errors.New("attestation failed"))
headers := map[string]string{"Custom-Header": "test-value"}
_, _, err := client.processRequest("GET", server.URL, nil, headers, http.StatusOK)
assert.NoError(t, err)
attestationProvider, err := NewAttestationProvider(mockProvider, attestation.SNPvTPM)
require.NoError(t, err)
provider := NewAttestedProvider(attestationProvider, DefaultCertificateSubject())
nonce := make([]byte, 64)
_, err = rand.Read(nonce)
require.NoError(t, err)
serverName := hex.EncodeToString(nonce) + ".nonce"
clientHello := &tls.ClientHelloInfo{ServerName: serverName}
_, err = provider.GetCertificate(clientHello)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to get attestation")
})
t.Run("UnexpectedStatusCode", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}))
defer server.Close()
t.Run("CASignedCertificateError", func(t *testing.T) {
mockProvider := new(mocks.Provider)
mockProvider.On("Attestation", mock.Anything, mock.Anything).Return([]byte("test-attestation"), nil)
_, _, err := client.processRequest("GET", server.URL, nil, nil, http.StatusOK)
attestationProvider, err := NewAttestationProvider(mockProvider, attestation.SNPvTPM)
require.NoError(t, err)
mockSDK := sdkmocks.NewSDK(t)
expectedCSR := certs.CSR{CSR: []byte("test-csr")}
sdkErr := errors.NewSDKError(errors.New("CA error"))
mockSDK.On("CreateCSR", mock.Anything, mock.Anything).Return(expectedCSR, errors.SDKError(nil))
mockSDK.On("IssueFromCSRInternal", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(certssdk.Certificate{}, sdkErr)
provider := NewAttestedCAProvider(attestationProvider, DefaultCertificateSubject(), mockSDK, "test-cvm", "test-token")
nonce := make([]byte, 64)
_, err = rand.Read(nonce)
require.NoError(t, err)
serverName := hex.EncodeToString(nonce) + ".nonce"
clientHello := &tls.ClientHelloInfo{ServerName: serverName}
_, err = provider.GetCertificate(clientHello)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to generate certificate")
})
}
// TestCertificateVerificationEdgeCases tests edge cases in certificate verification.
func TestCertificateVerificationEdgeCases(t *testing.T) {
tempDir, err := os.MkdirTemp("", "policy")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
attestationPB := prepVerifyAttReport(t)
err = setAttestationPolicy(attestationPB, tempDir)
require.NoError(t, err)
t.Run("VerifyPeerCertificateWithMultipleCerts", func(t *testing.T) {
verifier := NewCertificateVerifier(nil)
cert1 := createSelfSignedCert(t)
cert2 := createSelfSignedCert(t)
nonce := generateNonce(t)
err := verifier.VerifyPeerCertificate([][]byte{cert1.Raw, cert2.Raw}, nil, nonce)
assert.Error(t, err)
assert.Contains(t, err.Error(), "attestation extension not found")
})
t.Run("VerifyAttestationExtensionWithNoExtensions", func(t *testing.T) {
cert := createSelfSignedCert(t)
verifier := certificateVerifier{}
nonce := generateNonce(t)
err := verifier.verifyAttestationExtension(cert, nonce)
assert.Error(t, err)
assert.Contains(t, err.Error(), "attestation extension not found")
})
t.Run("VerifyAttestationExtensionWithWrongOID", func(t *testing.T) {
wrongOID := asn1.ObjectIdentifier{1, 2, 3, 4, 5}
extension := pkix.Extension{
Id: wrongOID,
Value: []byte("test-data"),
}
cert := generateTestCertificateWithExtensions(t, []pkix.Extension{extension})
verifier := certificateVerifier{}
nonce := generateNonce(t)
err := verifier.verifyAttestationExtension(cert, nonce)
assert.Error(t, err)
assert.Contains(t, err.Error(), "attestation extension not found")
})
t.Run("VerifyCertificateExtensionPlatformVerifierError", func(t *testing.T) {
verifier := certificateVerifier{}
invalidPlatformType := attestation.PlatformType(999)
err := verifier.verifyCertificateExtension([]byte("test-extension"), []byte("test-pubkey"), []byte("test-nonce"), invalidPlatformType)
assert.Error(t, err)
assert.Contains(t, err.Error(), "unsupported platform type")
})
}
@@ -793,7 +978,7 @@ func TestIntegrationScenarios(t *testing.T) {
mockProvider.On("Attestation", mock.Anything, mock.Anything).Return([]byte("mock-attestation"), nil)
// Create provider
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "")
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "", nil)
require.NoError(t, err)
// Generate certificate
@@ -826,19 +1011,18 @@ func TestIntegrationScenarios(t *testing.T) {
})
t.Run("FullCASignedFlow", func(t *testing.T) {
// Setup mock CA server
mockServer := createMockCAServer(t)
defer mockServer.Close()
mockSDK := sdkmocks.NewSDK(t)
expectedCSR := certs.CSR{CSR: []byte("test-csr")}
expectedCert := certssdk.Certificate{Certificate: generateTestCertPEM(t)}
mockSDK.On("CreateCSR", mock.Anything, mock.Anything).Return(expectedCSR, errors.SDKError(nil))
mockSDK.On("IssueFromCSRInternal", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(expectedCert, errors.SDKError(nil))
// Setup mock provider
mockProvider := new(mocks.Provider)
mockProvider.On("Attestation", mock.Anything, mock.Anything).Return([]byte("mock-attestation"), nil)
// Create CA-signed provider
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, mockServer.URL, "test-cvm")
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "test-token", "test-cvm-id", mockSDK)
require.NoError(t, err)
// Generate certificate
nonce := make([]byte, 64)
_, err = rand.Read(nonce)
require.NoError(t, err)
@@ -847,8 +1031,18 @@ func TestIntegrationScenarios(t *testing.T) {
clientHello := &tls.ClientHelloInfo{ServerName: serverName}
cert, err := provider.GetCertificate(clientHello)
assert.NoError(t, err)
assert.NotNil(t, cert)
require.NoError(t, err)
require.NotNil(t, cert)
require.NotEmpty(t, cert.Certificate)
require.NotNil(t, cert.PrivateKey)
parsedCert, err := x509.ParseCertificate(cert.Certificate[0])
require.NoError(t, err)
assert.NotNil(t, parsedCert.Subject)
mockProvider.AssertExpectations(t)
mockSDK.AssertExpectations(t)
})
}
@@ -857,7 +1051,7 @@ func TestConcurrentAccess(t *testing.T) {
mockProvider := new(mocks.Provider)
mockProvider.On("Attestation", mock.Anything, mock.Anything).Return([]byte("mock-attestation"), nil)
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "")
provider, err := NewProvider(mockProvider, attestation.SNPvTPM, "", "", nil)
require.NoError(t, err)
const numGoroutines = 10
+33 -7
View File
@@ -9,11 +9,14 @@ import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"strings"
"time"
"github.com/absmach/certs"
sdk "github.com/absmach/certs/sdk"
"github.com/ultravioletrs/cocos/pkg/attestation"
)
@@ -25,7 +28,8 @@ type CertificateProvider interface {
// AttestedCertificateProvider provides attested TLS certificates.
type attestedCertificateProvider struct {
attestationProvider AttestationProvider
caClient *CAClient
certsSDK sdk.SDK
agentToken string
subject CertificateSubject
useCA bool
cvmID string
@@ -50,12 +54,13 @@ func NewAttestedProvider(
func NewAttestedCAProvider(
attestationProvider AttestationProvider,
subject CertificateSubject,
caURL, cvmID string,
certsSDK sdk.SDK, cvmID, agentToken string,
) CertificateProvider {
return &attestedCertificateProvider{
attestationProvider: attestationProvider,
subject: subject,
caClient: NewCAClient(caURL),
certsSDK: certsSDK,
agentToken: agentToken,
useCA: true,
cvmID: cvmID,
ttl: time.Hour * 24 * 365, // Default 1 year
@@ -136,6 +141,7 @@ func (p *attestedCertificateProvider) generateCASignedCertificate(privateKey *ec
csrMetadata := certs.CSRMetadata{
Organization: []string{p.subject.Organization},
Country: []string{p.subject.Country},
CommonName: p.subject.CommonName,
Province: []string{p.subject.Province},
Locality: []string{p.subject.Locality},
StreetAddress: []string{p.subject.StreetAddress},
@@ -143,10 +149,30 @@ func (p *attestedCertificateProvider) generateCASignedCertificate(privateKey *ec
ExtraExtensions: []pkix.Extension{extension},
}
return p.caClient.RequestCertificate(csrMetadata, privateKey, p.cvmID, p.ttl)
csr, sdkerr := p.certsSDK.CreateCSR(csrMetadata, privateKey)
if sdkerr != nil {
return nil, fmt.Errorf("failed to create CSR: %w", sdkerr)
}
cert, err := p.certsSDK.IssueFromCSRInternal(p.cvmID, p.ttl.String(), string(csr.CSR), p.agentToken)
if err != nil {
return nil, err
}
cleanCertificateString := strings.ReplaceAll(cert.Certificate, "\\n", "\n")
block, rest := pem.Decode([]byte(cleanCertificateString))
if len(rest) != 0 {
return nil, fmt.Errorf("failed to decode certificate PEM: unexpected remaining data")
}
if block == nil {
return nil, fmt.Errorf("failed to decode certificate PEM: no PEM block found")
}
return block.Bytes, nil
}
func NewProvider(provider attestation.Provider, platformType attestation.PlatformType, caURL, cvmID string) (CertificateProvider, error) {
func NewProvider(provider attestation.Provider, platformType attestation.PlatformType, agentToken, cvmID string, certsSDK sdk.SDK) (CertificateProvider, error) {
attestationProvider, err := NewAttestationProvider(provider, platformType)
if err != nil {
return nil, fmt.Errorf("failed to create attestation provider: %w", err)
@@ -154,8 +180,8 @@ func NewProvider(provider attestation.Provider, platformType attestation.Platfor
subject := DefaultCertificateSubject()
if caURL != "" && cvmID != "" {
return NewAttestedCAProvider(attestationProvider, subject, caURL, cvmID), nil
if certsSDK != nil {
return NewAttestedCAProvider(attestationProvider, subject, certsSDK, cvmID, agentToken), nil
}
return NewAttestedProvider(attestationProvider, subject), nil
+1 -1
View File
@@ -110,7 +110,7 @@ func main() {
flagSetParseError := flagSet.Parse(os.Args[1:])
if flagSetParseError != nil {
log.Fatalf("Error parsing flagas: %v", flagSetParseError)
log.Fatalf("Error parsing flags: %v", flagSetParseError)
}
parsingError := !flagSet.Parsed()