mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
refactor: move acm domain and action adapters
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mulgadc/spinifex/spinifex/admin"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
"github.com/mulgadc/spinifex/spinifex/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -86,9 +86,9 @@ func runCertForceRenew(cmd *cobra.Command, _ []string) {
|
||||
defer cancel()
|
||||
|
||||
fmt.Printf("Force-renewing %s (account %s)...\n", certArn, accountID)
|
||||
out, err := utils.NATSRequest[handlers_acm.ForceRenewCertificateOutput](
|
||||
out, err := utils.NATSRequest[acmdomain.ForceRenewCertificateOutput](
|
||||
ctx, nc, "acm.ForceRenewCertificate",
|
||||
&handlers_acm.ForceRenewCertificateInput{CertificateArn: certArn},
|
||||
&acmdomain.ForceRenewCertificateInput{CertificateArn: certArn},
|
||||
30*time.Second, accountID,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -144,7 +144,7 @@ func runCertCreateTenantCA(cmd *cobra.Command, _ []string) {
|
||||
fmt.Println("Tenant CA already exists — reporting current state (use --regenerate to replace it):")
|
||||
}
|
||||
|
||||
ca, err := handlers_acm.LoadOrCreateTenantCA(certPath, keyPath, domains)
|
||||
ca, err := acmdomain.LoadOrCreateTenantCA(certPath, keyPath, domains)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -38,13 +38,13 @@ import (
|
||||
"github.com/mulgadc/spinifex/spinifex/admin"
|
||||
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
|
||||
"github.com/mulgadc/spinifex/spinifex/bootstrap/preflight"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/clustersize"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
"github.com/mulgadc/spinifex/spinifex/domains/ec2/instancetypes"
|
||||
handlers_ecr "github.com/mulgadc/spinifex/spinifex/domains/ecr"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/clustersize"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/telemetry"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
handlers_bedrock "github.com/mulgadc/spinifex/spinifex/handlers/bedrock"
|
||||
handlers_dns "github.com/mulgadc/spinifex/spinifex/handlers/dns"
|
||||
handlers_ec2_account "github.com/mulgadc/spinifex/spinifex/handlers/ec2/account"
|
||||
@@ -168,8 +168,8 @@ type Daemon struct {
|
||||
rdsReconciler *handlers_rds.Reconciler
|
||||
bedrockService *handlers_bedrock.Service
|
||||
bedrockReaper *handlers_bedrock.Reaper
|
||||
acmService *handlers_acm.ACMServiceImpl
|
||||
acmRenewalWorker *handlers_acm.Worker
|
||||
acmService *acmdomain.ACMServiceImpl
|
||||
acmRenewalWorker *acmdomain.Worker
|
||||
ochreVectorService handlers_ochrevector.VectorService
|
||||
ochreAppliance *handlers_ochrevector.Appliance
|
||||
ochreBackupService *handlers_ochrevector.BackupService
|
||||
@@ -2099,12 +2099,12 @@ func (d *Daemon) startCluster() error {
|
||||
// backoff — the key file can legitimately not be written yet during a
|
||||
// concurrent boot — but a master key that never arrives fails startCluster
|
||||
// after the retry window instead of leaving acmService permanently nil.
|
||||
d.acmService, err = initServiceWithRetry("ACM service", func() (*handlers_acm.ACMServiceImpl, error) {
|
||||
d.acmService, err = initServiceWithRetry("ACM service", func() (*acmdomain.ACMServiceImpl, error) {
|
||||
masterKey, mkErr := masterkey.ReadShared(filepath.Join(filepath.Dir(d.configPath), "master.key"))
|
||||
if mkErr != nil {
|
||||
return nil, fmt.Errorf("load ACM master key: %w", mkErr)
|
||||
}
|
||||
return handlers_acm.NewACMServiceImplWithNATS(d.ctx, d.config, d.natsConn, masterKey)
|
||||
return acmdomain.NewACMServiceImplWithNATS(d.ctx, d.config, d.natsConn, masterKey)
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize ACM service: %w", err)
|
||||
@@ -2134,7 +2134,7 @@ func (d *Daemon) startCluster() error {
|
||||
// operator can tell at a glance, from daemon startup logs alone, which one
|
||||
// they are in.
|
||||
configDir := filepath.Dir(d.configPath)
|
||||
tenantCA, tenantCAErr := handlers_acm.LoadTenantCA(admin.TenantCACertPath(configDir), admin.TenantCAKeyPath(configDir))
|
||||
tenantCA, tenantCAErr := acmdomain.LoadTenantCA(admin.TenantCACertPath(configDir), admin.TenantCAKeyPath(configDir))
|
||||
if tenantCAErr != nil {
|
||||
slog.Warn("ACM: tenant private CA not found; PRIVATE_CA certificate requests will fail until one is created",
|
||||
"err", tenantCAErr)
|
||||
@@ -2150,7 +2150,7 @@ func (d *Daemon) startCluster() error {
|
||||
// tenant CA loaded later (or never, on a public-certificates-only
|
||||
// deployment) is not a startup dependency — the worker just finds
|
||||
// nothing to renew until one is wired.
|
||||
d.acmRenewalWorker = handlers_acm.NewWorker(d.acmService, d.node)
|
||||
d.acmRenewalWorker = acmdomain.NewWorker(d.acmService, d.node)
|
||||
d.shutdownWg.Go(func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package gateway_acm
|
||||
package awsapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -1,10 +1,10 @@
|
||||
package gateway_acm_test
|
||||
package awsapi_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
awsapi "github.com/mulgadc/spinifex/spinifex/domains/acm/awsapi"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
gateway_acm "github.com/mulgadc/spinifex/spinifex/gateway/acm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -20,7 +20,7 @@ func certARN(id string) string {
|
||||
|
||||
func resolve(t *testing.T, action, body string) []string {
|
||||
t.Helper()
|
||||
resources, err := gateway_acm.ResourceARNs(action, testRegion, testAccountID, []byte(body))
|
||||
resources, err := awsapi.ResourceARNs(action, testRegion, testAccountID, []byte(body))
|
||||
require.NoError(t, err)
|
||||
return resources
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func TestResourceARNsUnparseableBody(t *testing.T) {
|
||||
// A body carrying two spellings of one field is rejected: the gate and the
|
||||
// handler would otherwise name different certificates.
|
||||
func TestResourceARNsAmbiguousBody(t *testing.T) {
|
||||
_, err := gateway_acm.ResourceARNs("DeleteCertificate", testRegion, testAccountID,
|
||||
_, err := awsapi.ResourceARNs("DeleteCertificate", testRegion, testAccountID,
|
||||
[]byte(`{"CertificateArn":"`+certARN("aaaa-1111")+`","certificateArn":"`+certARN("bbbb-2222")+`"}`))
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterValue, err.Error())
|
||||
@@ -111,7 +111,7 @@ func TestResourceARNsIdentifierIsAValue(t *testing.T) {
|
||||
// An action absent from the dispatch table cannot reach the resolver, but if one
|
||||
// ever did it fails closed rather than authorizing account-wide.
|
||||
func TestResourceARNsUnknownAction(t *testing.T) {
|
||||
_, err := gateway_acm.ResourceARNs("BogusAction", testRegion, testAccountID, []byte(`{}`))
|
||||
_, err := awsapi.ResourceARNs("BogusAction", testRegion, testAccountID, []byte(`{}`))
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, awserrors.ErrorInvalidAction, err.Error())
|
||||
}
|
||||
@@ -119,15 +119,15 @@ func TestResourceARNsUnknownAction(t *testing.T) {
|
||||
// Without a region or an account there is no ARN to build, and every action
|
||||
// falls back to the account-wide resource.
|
||||
func TestResourceARNsWithoutAnAnchor(t *testing.T) {
|
||||
for _, action := range gateway_acm.ScopedActions() {
|
||||
resources, err := gateway_acm.ResourceARNs(action, "", "", []byte(`{"CertificateArn":"`+certARN("aaaa-1111")+`"}`))
|
||||
for _, action := range awsapi.ScopedActions() {
|
||||
resources, err := awsapi.ResourceARNs(action, "", "", []byte(`{"CertificateArn":"`+certARN("aaaa-1111")+`"}`))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{"*"}, resources, "action %q", action)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasScope(t *testing.T) {
|
||||
assert.True(t, gateway_acm.HasScope("DeleteCertificate"))
|
||||
assert.False(t, gateway_acm.HasScope("BogusAction"))
|
||||
assert.Len(t, gateway_acm.ScopedActions(), 9)
|
||||
assert.True(t, awsapi.HasScope("DeleteCertificate"))
|
||||
assert.False(t, awsapi.HasScope("BogusAction"))
|
||||
assert.Len(t, awsapi.ScopedActions(), 9)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package gateway_acm
|
||||
package awsapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -14,6 +14,15 @@ import (
|
||||
// natsTimeout bounds the gateway's wait for a daemon-side ACM response.
|
||||
const natsTimeout = 30 * time.Second
|
||||
|
||||
// RequestCertificate — CertificateManager.RequestCertificate.
|
||||
func RequestCertificate(ctx context.Context, natsConn *nats.Conn, accountID string, body []byte) (*acm.RequestCertificateOutput, error) {
|
||||
input := new(acm.RequestCertificateInput)
|
||||
if err := unmarshalIfBody(body, input); err != nil {
|
||||
return nil, errors.New(awserrors.ErrorInvalidParameterValue)
|
||||
}
|
||||
return utils.NATSRequest[acm.RequestCertificateOutput](ctx, natsConn, "acm.RequestCertificate", input, natsTimeout, accountID)
|
||||
}
|
||||
|
||||
// ImportCertificate — CertificateManager.ImportCertificate.
|
||||
func ImportCertificate(ctx context.Context, natsConn *nats.Conn, accountID string, body []byte) (*acm.ImportCertificateOutput, error) {
|
||||
input := new(acm.ImportCertificateInput)
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
package gateway_acm
|
||||
package awsapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Package gateway_acm is the HTTP-side glue between awsgw and the ACM handlers.
|
||||
// ACM speaks AWS JSON 1.1 (X-Amz-Target dispatch); errors are handled centrally
|
||||
// by the shared gateway ErrorHandler.
|
||||
package gateway_acm
|
||||
// Package awsapi adapts ACM's AWS JSON 1.1 actions to the ACM domain's
|
||||
// NATS-backed service contract. Generic gateway routing and authorization stay
|
||||
// at the ingress boundary.
|
||||
package awsapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,5 @@
|
||||
package handlers_acm
|
||||
// Package acm owns ACM certificate state, issuance, renewal and AWS action adapters.
|
||||
package acm
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
// renewal.go implements the PRIVATE_CA renewal worker described in the ACM
|
||||
// design doc's "Renewal" section: a scan-and-lease worker, sharing the
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -32,7 +32,7 @@ const (
|
||||
|
||||
// CertAuthority issues leaf certificates from the tenant private CA and
|
||||
// authorizes domains against the CA's own x509 name constraints. Satisfied by
|
||||
// *TenantCA (handlers/acm/privateca.go), which is implemented separately;
|
||||
// *TenantCA (privateca.go), which is implemented separately;
|
||||
// defined here as a narrow interface so this package builds and is testable
|
||||
// with a fake independently of that file.
|
||||
type CertAuthority interface {
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -20,10 +20,10 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
|
||||
"github.com/aws/aws-sdk-go/service/acm"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package handlers_acm
|
||||
package acm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
+14
-32
@@ -2,65 +2,47 @@ package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/acm"
|
||||
acmawsapi "github.com/mulgadc/spinifex/spinifex/domains/acm/awsapi"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
gateway_acm "github.com/mulgadc/spinifex/spinifex/gateway/acm"
|
||||
"github.com/mulgadc/spinifex/spinifex/utils"
|
||||
)
|
||||
|
||||
// acmNATSTimeout bounds the gateway's wait for a daemon-side ACM response.
|
||||
// RequestCertificate itself returns immediately (issuance is asynchronous),
|
||||
// so this is a network/queueing budget, not an issuance one.
|
||||
const acmNATSTimeout = 30 * time.Second
|
||||
|
||||
// acmHandler invokes a per-action ACM gateway function.
|
||||
// acmHandler invokes a per-action ACM domain adapter after generic gateway
|
||||
// authentication and authorization have completed.
|
||||
type acmHandler func(ctx context.Context, gw *GatewayConfig, accountID string, body []byte) (any, error)
|
||||
|
||||
// acmActions maps the action suffix of X-Amz-Target (CertificateManager.<Action>) to its handler.
|
||||
var acmActions = map[string]acmHandler{
|
||||
"ImportCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.ImportCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.ImportCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
// RequestCertificate calls the daemon over NATS directly (rather than
|
||||
// through package gateway_acm, which does not yet have a helper for it) —
|
||||
// the same "acm.RequestCertificate" subject and request/response shape
|
||||
// utils.NATSRequest uses everywhere else in this table.
|
||||
"RequestCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
input := new(acm.RequestCertificateInput)
|
||||
if len(b) > 0 {
|
||||
if err := json.Unmarshal(b, input); err != nil {
|
||||
return nil, errors.New(awserrors.ErrorInvalidParameterValue)
|
||||
}
|
||||
}
|
||||
return utils.NATSRequest[acm.RequestCertificateOutput](ctx, gw.NATSConn, "acm.RequestCertificate", input, acmNATSTimeout, acct)
|
||||
return acmawsapi.RequestCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"DescribeCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.DescribeCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.DescribeCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"GetCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.GetCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.GetCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"ListCertificates": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.ListCertificates(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.ListCertificates(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"DeleteCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.DeleteCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.DeleteCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"ListTagsForCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.ListTagsForCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.ListTagsForCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"AddTagsToCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.AddTagsToCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.AddTagsToCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
"RemoveTagsFromCertificate": func(ctx context.Context, gw *GatewayConfig, acct string, b []byte) (any, error) {
|
||||
return gateway_acm.RemoveTagsFromCertificate(ctx, gw.NATSConn, acct, b)
|
||||
return acmawsapi.RemoveTagsFromCertificate(ctx, gw.NATSConn, acct, b)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -103,7 +85,7 @@ func (gw *GatewayConfig) ACM_Request(w http.ResponseWriter, r *http.Request) err
|
||||
return err
|
||||
}
|
||||
|
||||
resources, err := gateway_acm.ResourceARNs(action, gw.Region, accountID, body)
|
||||
resources, err := acmawsapi.ResourceARNs(action, gw.Region, accountID, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,6 +102,6 @@ func (gw *GatewayConfig) ACM_Request(w http.ResponseWriter, r *http.Request) err
|
||||
return err
|
||||
}
|
||||
|
||||
gateway_acm.WriteJSONResponse(w, output)
|
||||
acmawsapi.WriteJSONResponse(w, output)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ package gateway
|
||||
import (
|
||||
"testing"
|
||||
|
||||
gateway_acm "github.com/mulgadc/spinifex/spinifex/gateway/acm"
|
||||
acmawsapi "github.com/mulgadc/spinifex/spinifex/domains/acm/awsapi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -15,13 +15,13 @@ import (
|
||||
// behind by a deleted or renamed action fails too.
|
||||
func TestACMScopeTableIsExhaustive(t *testing.T) {
|
||||
for action := range acmActions {
|
||||
assert.True(t, gateway_acm.HasScope(action),
|
||||
"acm action %q has no resource scope entry: add one to acmScopes in gateway/acm/authz.go", action)
|
||||
assert.True(t, acmawsapi.HasScope(action),
|
||||
"acm action %q has no resource scope entry: add one to domains/acm/awsapi/authz.go", action)
|
||||
}
|
||||
|
||||
for _, action := range gateway_acm.ScopedActions() {
|
||||
for _, action := range acmawsapi.ScopedActions() {
|
||||
_, ok := acmActions[action]
|
||||
assert.True(t, ok,
|
||||
"acmScopes has an entry for %q, which the dispatch table does not serve: remove it from gateway/acm/authz.go", action)
|
||||
"acmScopes has an entry for %q, which the dispatch table does not serve: remove it from domains/acm/awsapi/authz.go", action)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mulgadc/bluebottle/pkg/sigv4"
|
||||
acmawsapi "github.com/mulgadc/spinifex/spinifex/domains/acm/awsapi"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
gateway_acm "github.com/mulgadc/spinifex/spinifex/gateway/acm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -125,7 +125,7 @@ func TestACMRequest_ListIsAccountLevel(t *testing.T) {
|
||||
func TestACMRequest_WildcardPolicyStillPermitsEveryAction(t *testing.T) {
|
||||
gw := scopedPolicyGateway(statement("Allow", "acm:*", "*"))
|
||||
|
||||
for _, action := range gateway_acm.ScopedActions() {
|
||||
for _, action := range acmawsapi.ScopedActions() {
|
||||
t.Run(action, func(t *testing.T) {
|
||||
assertPermitted(t, dispatchACM(t, gw, action, `{"CertificateArn":"`+acmCertARN("aaaa-1111")+`"}`))
|
||||
})
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/acm"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -343,7 +343,7 @@ func TestReconcileCertInUseIndex_RestoresRenewalFanOut(t *testing.T) {
|
||||
|
||||
elbv2Svc, err := NewELBv2ServiceImplWithNATS(nil, nc, masterKey)
|
||||
require.NoError(t, err)
|
||||
acmSvc, err := handlers_acm.NewACMServiceImplWithNATS(context.Background(), nil, nc, masterKey)
|
||||
acmSvc, err := acmdomain.NewACMServiceImplWithNATS(context.Background(), nil, nc, masterKey)
|
||||
require.NoError(t, err)
|
||||
acmSvc.CertMaterialUpdated = elbv2Svc.UpdateStoredConfigForCert
|
||||
|
||||
@@ -443,7 +443,7 @@ func TestACMReimport_FansOutToInUseLoadBalancer(t *testing.T) {
|
||||
|
||||
elbv2Svc, err := NewELBv2ServiceImplWithNATS(nil, nc, masterKey)
|
||||
require.NoError(t, err)
|
||||
acmSvc, err := handlers_acm.NewACMServiceImplWithNATS(context.Background(), nil, nc, masterKey)
|
||||
acmSvc, err := acmdomain.NewACMServiceImplWithNATS(context.Background(), nil, nc, masterKey)
|
||||
require.NoError(t, err)
|
||||
// Mirrors the daemon.go wiring between the two services.
|
||||
acmSvc.CertMaterialUpdated = elbv2Svc.UpdateStoredConfigForCert
|
||||
|
||||
@@ -13,11 +13,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
"github.com/mulgadc/spinifex/spinifex/lbagent"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
"github.com/mulgadc/spinifex/spinifex/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -105,7 +105,7 @@ func TestConfigCertHash_ChangesOnRotation(t *testing.T) {
|
||||
|
||||
func putTestCert(t *testing.T, svc *ELBv2ServiceImpl, arn, account, leaf, chain, key string) {
|
||||
t.Helper()
|
||||
require.NoError(t, svc.acmStore.PutCert(t.Context(), &handlers_acm.CertRecord{
|
||||
require.NoError(t, svc.acmStore.PutCert(t.Context(), &acmdomain.CertRecord{
|
||||
CertificateArn: arn,
|
||||
AccountID: account,
|
||||
Certificate: leaf,
|
||||
@@ -155,7 +155,7 @@ func TestResolveCertPEM_CrossesACMServiceKeyBoundary(t *testing.T) {
|
||||
|
||||
// ACM-service-style writer: its own Store over the same bucket, wired with
|
||||
// the same deployment key rather than svc's own acmStore.
|
||||
acmStore, err := handlers_acm.NewStore(t.Context(), nc, masterKey)
|
||||
acmStore, err := acmdomain.NewStore(t.Context(), nc, masterKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
// A realistic EC private key PEM, not a placeholder — a non-PEM value
|
||||
@@ -168,7 +168,7 @@ func TestResolveCertPEM_CrossesACMServiceKeyBoundary(t *testing.T) {
|
||||
keyPEM := string(pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}))
|
||||
|
||||
arn := "arn:aws:acm:ap-southeast-2:123456789012:certificate/cross-boundary"
|
||||
require.NoError(t, acmStore.PutCert(t.Context(), &handlers_acm.CertRecord{
|
||||
require.NoError(t, acmStore.PutCert(t.Context(), &acmdomain.CertRecord{
|
||||
CertificateArn: arn,
|
||||
AccountID: testAccountID,
|
||||
Certificate: "LEAF",
|
||||
|
||||
@@ -20,11 +20,11 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
resourcearn "github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
handlers_dns "github.com/mulgadc/spinifex/spinifex/handlers/dns"
|
||||
handlers_ec2_vpc "github.com/mulgadc/spinifex/spinifex/handlers/ec2/vpc"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
@@ -103,7 +103,7 @@ var _ ELBv2Service = (*ELBv2ServiceImpl)(nil)
|
||||
type ELBv2ServiceImpl struct {
|
||||
config *config.Config
|
||||
store *Store
|
||||
acmStore *handlers_acm.Store // resolves listener cert ARNs → PEM; nil-safe (HTTPS unavailable when nil)
|
||||
acmStore *acmdomain.Store // resolves listener cert ARNs → PEM; nil-safe (HTTPS unavailable when nil)
|
||||
nc *nats.Conn // NATS connection for JetStream KV store
|
||||
VPCService *handlers_ec2_vpc.VPCServiceImpl // nil-safe: ENI ops skipped when nil (e.g. in tests)
|
||||
InstanceLauncher SystemInstanceLauncher // nil-safe: system VM ops skipped when nil
|
||||
@@ -173,7 +173,7 @@ func NewELBv2ServiceImplWithNATS(cfg *config.Config, nc *nats.Conn, masterKey []
|
||||
// found" everywhere it is consulted (resolveCertPEM, validateListenerCerts),
|
||||
// so a construction failure here must fail the whole service rather than
|
||||
// silently degrade every HTTPS listener.
|
||||
acmStore, acmErr := handlers_acm.NewStore(ctx, nc, masterKey)
|
||||
acmStore, acmErr := acmdomain.NewStore(ctx, nc, masterKey)
|
||||
if acmErr != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("failed to create ELBv2 ACM store: %w", acmErr)
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
awscreds "github.com/aws/aws-sdk-go/aws/credentials"
|
||||
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
acmawsapi "github.com/mulgadc/spinifex/spinifex/domains/acm/awsapi"
|
||||
awsapi "github.com/mulgadc/spinifex/spinifex/domains/ecr/awsapi"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
gateway_acm "github.com/mulgadc/spinifex/spinifex/gateway/acm"
|
||||
gateway_ecs "github.com/mulgadc/spinifex/spinifex/gateway/ecs"
|
||||
gateway_eks "github.com/mulgadc/spinifex/spinifex/gateway/eks"
|
||||
gateway_elbv2 "github.com/mulgadc/spinifex/spinifex/gateway/elbv2"
|
||||
@@ -329,7 +329,7 @@ func sameHelper(casedAction string) string {
|
||||
|
||||
func scopedServices() []scopedService {
|
||||
return []scopedService{
|
||||
{name: "acm", actions: gateway_acm.ScopedActions(), uncased: map[string]string{
|
||||
{name: "acm", actions: acmawsapi.ScopedActions(), uncased: map[string]string{
|
||||
"GetCertificate": sameHelper("DescribeCertificate"),
|
||||
"ListTagsForCertificate": sameHelper("DescribeCertificate"),
|
||||
"AddTagsToCertificate": sameHelper("DescribeCertificate"),
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
|
||||
handlers_acm "github.com/mulgadc/spinifex/spinifex/handlers/acm"
|
||||
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
|
||||
handlers_ecs "github.com/mulgadc/spinifex/spinifex/handlers/ecs"
|
||||
handlers_eks "github.com/mulgadc/spinifex/spinifex/handlers/eks"
|
||||
handlers_elbv2 "github.com/mulgadc/spinifex/spinifex/handlers/elbv2"
|
||||
@@ -26,12 +26,12 @@ func StartServiceDaemonLite(t *testing.T, gw *Gateway) {
|
||||
masterKey, err := handlers_iam.GenerateMasterKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
acm, err := handlers_acm.NewACMServiceImplWithNATS(t.Context(), cfg, nc, masterKey)
|
||||
acm, err := acmdomain.NewACMServiceImplWithNATS(t.Context(), cfg, nc, masterKey)
|
||||
require.NoError(t, err, "construct ACM service")
|
||||
// Without a tenant CA no mode can issue, so every RequestCertificate would
|
||||
// be refused. The generated requests name example.com domains.
|
||||
caDir := t.TempDir()
|
||||
acm.TenantCA, err = handlers_acm.LoadOrCreateTenantCA(filepath.Join(caDir, "ca.pem"), filepath.Join(caDir, "ca.key"), []string{"example.com"})
|
||||
acm.TenantCA, err = acmdomain.LoadOrCreateTenantCA(filepath.Join(caDir, "ca.pem"), filepath.Join(caDir, "ca.key"), []string{"example.com"})
|
||||
require.NoError(t, err, "create ACM tenant CA")
|
||||
subscribeServiceMethods(t, nc, "acm", acm)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user