312 lines
9.4 KiB
Go
312 lines
9.4 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"math/big"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"floci-sdk-test-go/internal/testutil"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/service/acm"
|
|
acmtypes "github.com/aws/aws-sdk-go-v2/service/acm/types"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// generateSelfSignedCert creates a self-signed certificate and private key in PEM format.
|
|
func generateSelfSignedCert() (certPEM, keyPEM []byte) {
|
|
key, _ := rsa.GenerateKey(rand.Reader, 2048)
|
|
tmpl := &x509.Certificate{
|
|
SerialNumber: big.NewInt(1),
|
|
Subject: pkix.Name{CommonName: "test.example.com"},
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().Add(365 * 24 * time.Hour),
|
|
}
|
|
certDER, _ := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
|
|
certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
|
|
keyPEM = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
|
|
return
|
|
}
|
|
|
|
func TestACM(t *testing.T) {
|
|
ctx := context.Background()
|
|
svc := testutil.ACMClient()
|
|
var certARN string
|
|
|
|
t.Run("RequestCertificate", func(t *testing.T) {
|
|
r, err := svc.RequestCertificate(ctx, &acm.RequestCertificateInput{
|
|
DomainName: aws.String("go-test.example.com"),
|
|
})
|
|
require.NoError(t, err)
|
|
certARN = aws.ToString(r.CertificateArn)
|
|
assert.NotEmpty(t, certARN)
|
|
assert.True(t, strings.HasPrefix(certARN, "arn:aws:acm:"), "ARN should match arn:aws:acm pattern, got: %s", certARN)
|
|
})
|
|
|
|
t.Run("DescribeCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
r, err := svc.DescribeCertificate(ctx, &acm.DescribeCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "go-test.example.com", aws.ToString(r.Certificate.DomainName))
|
|
assert.Equal(t, acmtypes.CertificateStatusIssued, r.Certificate.Status)
|
|
})
|
|
|
|
t.Run("GetCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
r, err := svc.GetCertificate(ctx, &acm.GetCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, aws.ToString(r.Certificate))
|
|
})
|
|
|
|
t.Run("ListCertificates", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
r, err := svc.ListCertificates(ctx, &acm.ListCertificatesInput{})
|
|
require.NoError(t, err)
|
|
|
|
found := false
|
|
for _, c := range r.CertificateSummaryList {
|
|
if aws.ToString(c.CertificateArn) == certARN {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "Certificate %s should appear in list", certARN)
|
|
})
|
|
|
|
t.Run("AddTagsToCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
_, err := svc.AddTagsToCertificate(ctx, &acm.AddTagsToCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
Tags: []acmtypes.Tag{
|
|
{Key: aws.String("Env"), Value: aws.String("test")},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
r, err := svc.ListTagsForCertificate(ctx, &acm.ListTagsForCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
found := false
|
|
for _, tag := range r.Tags {
|
|
if aws.ToString(tag.Key) == "Env" && aws.ToString(tag.Value) == "test" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "Tag Env=test should be present")
|
|
})
|
|
|
|
t.Run("ListTagsForCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
r, err := svc.ListTagsForCertificate(ctx, &acm.ListTagsForCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
found := false
|
|
for _, tag := range r.Tags {
|
|
if aws.ToString(tag.Key) == "Env" && aws.ToString(tag.Value) == "test" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "Tag Env=test should still be present")
|
|
})
|
|
|
|
t.Run("RemoveTagsFromCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
_, err := svc.RemoveTagsFromCertificate(ctx, &acm.RemoveTagsFromCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
Tags: []acmtypes.Tag{
|
|
{Key: aws.String("Env"), Value: aws.String("test")},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
r, err := svc.ListTagsForCertificate(ctx, &acm.ListTagsForCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
for _, tag := range r.Tags {
|
|
assert.NotEqual(t, "Env", aws.ToString(tag.Key), "Tag Env should have been removed")
|
|
}
|
|
})
|
|
|
|
t.Run("DeleteCertificate", func(t *testing.T) {
|
|
if certARN == "" {
|
|
t.Skip("No certificate ARN from RequestCertificate")
|
|
}
|
|
_, err := svc.DeleteCertificate(ctx, &acm.DeleteCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
_, err = svc.DescribeCertificate(ctx, &acm.DescribeCertificateInput{
|
|
CertificateArn: aws.String(certARN),
|
|
})
|
|
assert.Error(t, err, "DescribeCertificate should fail after deletion")
|
|
})
|
|
}
|
|
|
|
func TestACMImportExport(t *testing.T) {
|
|
ctx := context.Background()
|
|
svc := testutil.ACMClient()
|
|
certPEM, keyPEM := generateSelfSignedCert()
|
|
var importedARN string
|
|
|
|
t.Cleanup(func() {
|
|
if importedARN != "" {
|
|
svc.DeleteCertificate(ctx, &acm.DeleteCertificateInput{
|
|
CertificateArn: aws.String(importedARN),
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("ImportCertificate", func(t *testing.T) {
|
|
r, err := svc.ImportCertificate(ctx, &acm.ImportCertificateInput{
|
|
Certificate: certPEM,
|
|
PrivateKey: keyPEM,
|
|
})
|
|
require.NoError(t, err)
|
|
importedARN = aws.ToString(r.CertificateArn)
|
|
assert.NotEmpty(t, importedARN)
|
|
assert.True(t, strings.HasPrefix(importedARN, "arn:aws:acm:"), "ARN should match arn:aws:acm pattern, got: %s", importedARN)
|
|
})
|
|
|
|
t.Run("GetImportedCertificate", func(t *testing.T) {
|
|
if importedARN == "" {
|
|
t.Skip("No imported certificate ARN")
|
|
}
|
|
r, err := svc.GetCertificate(ctx, &acm.GetCertificateInput{
|
|
CertificateArn: aws.String(importedARN),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, aws.ToString(r.Certificate))
|
|
})
|
|
|
|
t.Run("ExportCertificate", func(t *testing.T) {
|
|
if importedARN == "" {
|
|
t.Skip("No imported certificate ARN")
|
|
}
|
|
r, err := svc.ExportCertificate(ctx, &acm.ExportCertificateInput{
|
|
CertificateArn: aws.String(importedARN),
|
|
Passphrase: []byte("test-passphrase"),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, aws.ToString(r.Certificate), "Exported certificate body should not be empty")
|
|
assert.NotEmpty(t, aws.ToString(r.PrivateKey), "Exported private key should not be empty")
|
|
})
|
|
|
|
t.Run("ExportRequestedCertificateFails", func(t *testing.T) {
|
|
// Request a certificate (not imported) - export should fail
|
|
reqResult, err := svc.RequestCertificate(ctx, &acm.RequestCertificateInput{
|
|
DomainName: aws.String("go-export-fail.example.com"),
|
|
})
|
|
require.NoError(t, err)
|
|
requestedARN := aws.ToString(reqResult.CertificateArn)
|
|
|
|
t.Cleanup(func() {
|
|
svc.DeleteCertificate(ctx, &acm.DeleteCertificateInput{
|
|
CertificateArn: aws.String(requestedARN),
|
|
})
|
|
})
|
|
|
|
_, err = svc.ExportCertificate(ctx, &acm.ExportCertificateInput{
|
|
CertificateArn: aws.String(requestedARN),
|
|
Passphrase: []byte("test-passphrase"),
|
|
})
|
|
assert.Error(t, err, "ExportCertificate should fail for a requested (non-imported) certificate")
|
|
})
|
|
}
|
|
|
|
func TestACMAccountConfiguration(t *testing.T) {
|
|
ctx := context.Background()
|
|
svc := testutil.ACMClient()
|
|
|
|
_, err := svc.PutAccountConfiguration(ctx, &acm.PutAccountConfigurationInput{
|
|
ExpiryEvents: &acmtypes.ExpiryEventsConfiguration{
|
|
DaysBeforeExpiry: aws.Int32(45),
|
|
},
|
|
IdempotencyToken: aws.String("go-test-idempotency-token"),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
r, err := svc.GetAccountConfiguration(ctx, &acm.GetAccountConfigurationInput{})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, r.ExpiryEvents)
|
|
assert.Equal(t, int32(45), aws.ToInt32(r.ExpiryEvents.DaysBeforeExpiry))
|
|
}
|
|
|
|
func TestACMErrorHandling(t *testing.T) {
|
|
ctx := context.Background()
|
|
svc := testutil.ACMClient()
|
|
|
|
t.Run("DescribeNonExistent", func(t *testing.T) {
|
|
_, err := svc.DescribeCertificate(ctx, &acm.DescribeCertificateInput{
|
|
CertificateArn: aws.String("arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000"),
|
|
})
|
|
assert.Error(t, err, "DescribeCertificate should fail for non-existent ARN")
|
|
})
|
|
|
|
t.Run("RequestWithSANs", func(t *testing.T) {
|
|
r, err := svc.RequestCertificate(ctx, &acm.RequestCertificateInput{
|
|
DomainName: aws.String("go-san-test.example.com"),
|
|
SubjectAlternativeNames: []string{
|
|
"go-san-test.example.com",
|
|
"www.go-san-test.example.com",
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
sanARN := aws.ToString(r.CertificateArn)
|
|
assert.NotEmpty(t, sanARN)
|
|
|
|
t.Cleanup(func() {
|
|
svc.DeleteCertificate(ctx, &acm.DeleteCertificateInput{
|
|
CertificateArn: aws.String(sanARN),
|
|
})
|
|
})
|
|
|
|
desc, err := svc.DescribeCertificate(ctx, &acm.DescribeCertificateInput{
|
|
CertificateArn: aws.String(sanARN),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Contains(t, desc.Certificate.SubjectAlternativeNames, "go-san-test.example.com")
|
|
assert.Contains(t, desc.Certificate.SubjectAlternativeNames, "www.go-san-test.example.com")
|
|
})
|
|
|
|
t.Run("ImportInvalidPEM", func(t *testing.T) {
|
|
_, err := svc.ImportCertificate(ctx, &acm.ImportCertificateInput{
|
|
Certificate: []byte("not-valid-pem-data"),
|
|
PrivateKey: []byte("not-valid-key-data"),
|
|
})
|
|
assert.Error(t, err, "ImportCertificate should fail with invalid PEM data")
|
|
})
|
|
}
|