Skip to content

Commit 270e8e7

Browse files
Egor Novikovbmsiegel
authored andcommitted
Add role assumption for Issuer
Signed-off-by: Egor Novikov <[email protected]> Signed-off-by: Brady Siegel <[email protected]>
1 parent d1d373b commit 270e8e7

File tree

13 files changed

+113
-19
lines changed

13 files changed

+113
-19
lines changed

charts/aws-pca-issuer/crds/awspca.cert-manager.io_awspcaclusterissuers.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ spec:
4646
region:
4747
description: Should contain the AWS region if it cannot be inferred
4848
type: string
49+
role:
50+
description: Specifies the ARN of role to assume when issuing certificates.
51+
type: string
4952
secretRef:
5053
description: Needs to be specified if you want to authorize with AWS
5154
using an access and secret key

charts/aws-pca-issuer/crds/awspca.cert-manager.io_awspcaissuers.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ spec:
4545
region:
4646
description: Should contain the AWS region if it cannot be inferred
4747
type: string
48+
role:
49+
description: Specifies the ARN of role to assume when issuing certificates.
50+
type: string
4851
secretRef:
4952
description: Needs to be specified if you want to authorize with AWS
5053
using an access and secret key

config/crd/bases/awspca.cert-manager.io_awspcaclusterissuers.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ spec:
4646
region:
4747
description: Should contain the AWS region if it cannot be inferred
4848
type: string
49+
role:
50+
description: Specifies the ARN of role to assume when issuing certificates.
51+
type: string
4952
secretRef:
5053
description: Needs to be specified if you want to authorize with AWS
5154
using an access and secret key

config/crd/bases/awspca.cert-manager.io_awspcaissuers.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ spec:
4545
region:
4646
description: Should contain the AWS region if it cannot be inferred
4747
type: string
48+
role:
49+
description: Specifies the ARN of role to assume when issuing certificates.
50+
type: string
4851
secretRef:
4952
description: Needs to be specified if you want to authorize with AWS
5053
using an access and secret key
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: awspca.cert-manager.io/v1beta1
2+
kind: AWSPCAClusterIssuer
3+
metadata:
4+
name: example
5+
spec:
6+
arn: <some-pca-arn>
7+
role: <some-role-arn>
8+
region: us-west-2

e2e/aws_helpers.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func getAccountID(ctx context.Context, cfg aws.Config) string {
296296
return *callerID.Account
297297
}
298298

299-
func getPartition(ctx context.Context, cfg aws.Config) string {
299+
func getCallerIdentity(ctx context.Context, cfg aws.Config) *sts.GetCallerIdentityOutput {
300300
stsClient := sts.NewFromConfig(cfg)
301301

302302
callerID, callerErr := stsClient.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
@@ -305,6 +305,12 @@ func getPartition(ctx context.Context, cfg aws.Config) string {
305305
panic(callerErr.Error())
306306
}
307307

308+
return callerID
309+
}
310+
311+
func getPartition(ctx context.Context, cfg aws.Config) string {
312+
callerID := getCallerIdentity(ctx, cfg)
313+
308314
parsedArn, parseErr := arn.Parse(*callerID.Arn)
309315
if parseErr != nil {
310316
return "aws"

e2e/awspcaissuer_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import (
55
"fmt"
66
"log"
77
"os"
8+
"regexp"
89
"strings"
910
"testing"
1011
"time"
1112

1213
"github.com/aws/aws-sdk-go-v2/aws"
14+
"github.com/aws/aws-sdk-go-v2/aws/arn"
1315
"github.com/aws/aws-sdk-go-v2/config"
1416
"github.com/cert-manager/aws-privateca-issuer/pkg/api/v1beta1"
1517
clientV1beta1 "github.com/cert-manager/aws-privateca-issuer/pkg/clientset/v1beta1"
@@ -31,7 +33,7 @@ type TestContext struct {
3133
xaCfg aws.Config
3234
caArns map[string]string
3335

34-
region, partition, accessKey, secretKey, endEntityResourceShareArn, subordinateCaResourceShareArn, userName, policyArn string
36+
region, partition, accessKey, secretKey, endEntityResourceShareArn, subordinateCaResourceShareArn, userName, policyArn, accountId, domain string
3537
}
3638

3739
// These are variables specific to each test
@@ -111,7 +113,23 @@ func InitializeTestSuite(suiteCtx *godog.TestSuiteContext) {
111113
panic(cfgErr.Error())
112114
}
113115

114-
testContext.partition = getPartition(ctx, cfg)
116+
callerID := getCallerIdentity(ctx, cfg)
117+
testContext.accountId = *callerID.Account
118+
119+
parsedArn, parseErr := arn.Parse(*callerID.Arn)
120+
if parseErr != nil {
121+
panic("Failed to parse caller identity ARN: " + parseErr.Error())
122+
}
123+
124+
testContext.partition = parsedArn.Partition
125+
126+
// Match the complete resource: assumed-role/RoleName-DOMAIN-region/i-xxxxxxxxx
127+
re := regexp.MustCompile(`^assumed-role/[^-]+-([^-]+)-[^/]+/i-[a-f0-9]+$`)
128+
matches := re.FindStringSubmatch(parsedArn.Resource)
129+
if len(matches) < 2 {
130+
panic("Failed to extract domain from caller identity resource: " + parsedArn.Resource)
131+
}
132+
testContext.domain = matches[1]
115133

116134
testContext.iclient, err = clientV1beta1.NewForConfig(clientConfig)
117135

@@ -217,8 +235,10 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
217235
ctx.Step(`^I create a namespace`, issuerContext.createNamespace)
218236
ctx.Step(`^I create a Secret with keys ([A-Za-z_]+) and ([A-Za-z_]+) for my AWS credentials$`, issuerContext.createSecret)
219237
ctx.Step(`^I create an AWSPCAClusterIssuer using a (RSA|ECDSA|XA) CA$`, issuerContext.createClusterIssuer)
238+
ctx.Step(`^I create an AWSPCAClusterIssuer with role assumption$`, issuerContext.createClusterIssuerWithRole)
220239
ctx.Step(`^I delete the AWSPCAClusterIssuer$`, issuerContext.deleteClusterIssuer)
221240
ctx.Step(`^I create an AWSPCAIssuer using a (RSA|ECDSA|XA) CA$`, issuerContext.createNamespaceIssuer)
241+
ctx.Step(`^I create an AWSPCAIssuer with role assumption$`, issuerContext.createNamespaceIssuerWithRole)
222242
ctx.Step(`^I issue a (SHORT_VALIDITY|RSA|ECDSA|CA) certificate$`, issuerContext.issueCertificate)
223243
ctx.Step(`^the certificate should be issued successfully$`, issuerContext.verifyCertificateIssued)
224244
ctx.Step(`^the certificate request has been created$`, issuerContext.verifyCertificateRequestIsCreated)

e2e/clusterissuer_steps.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ import (
1313
)
1414

1515
func (issCtx *IssuerContext) createClusterIssuer(ctx context.Context, caType string) error {
16+
return issCtx.createClusterIssuerWithSpec(ctx, caType, getIssuerSpec(caType))
17+
}
18+
19+
func (issCtx *IssuerContext) createClusterIssuerWithRole(ctx context.Context) error {
20+
return issCtx.createClusterIssuerWithSpec(ctx, "RSA", getIssuerSpecWithRole("RSA"))
21+
}
22+
23+
func (issCtx *IssuerContext) createClusterIssuerWithSpec(ctx context.Context, caType string, spec v1beta1.AWSPCAIssuerSpec) error {
1624
if issCtx.issuerName == "" {
1725
issCtx.issuerName = uuid.New().String() + "--cluster-issuer--" + strings.ToLower(caType)
1826
}
27+
1928
issCtx.issuerType = "AWSPCAClusterIssuer"
2029
issSpec := v1beta1.AWSPCAClusterIssuer{
2130
ObjectMeta: metav1.ObjectMeta{Name: issCtx.issuerName},
22-
Spec: getIssuerSpec(caType),
31+
Spec: spec,
2332
}
2433

2534
if issCtx.secretRef != (v1beta1.AWSCredentialsSecretReference{}) {

e2e/common_steps.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ func getIssuerSpec(caType string) v1beta1.AWSPCAIssuerSpec {
3434
}
3535
}
3636

37+
func getIssuerSpecWithRole(caType string) v1beta1.AWSPCAIssuerSpec {
38+
spec := getIssuerSpec(caType)
39+
spec.Role = fmt.Sprintf("arn:%s:iam::%s:role/IssuerTestRole-%s-%s", testContext.partition, testContext.accountId, testContext.domain, testContext.region)
40+
return spec
41+
}
42+
3743
func (issCtx *IssuerContext) createNamespace(ctx context.Context) error {
3844
namespaceName := "pca-issuer-ns-" + uuid.New().String()
3945
namespace := v1.Namespace{
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@RoleAssumption
2+
Feature: Issue certificates using role assumption
3+
As a user of the aws-privateca-issuer
4+
I need to be able to issue certificates using role assumption
5+
6+
Scenario: Issue a certificate with a ClusterIssuer using role assumption
7+
Given I create an AWSPCAClusterIssuer with role assumption
8+
When I issue a RSA certificate
9+
Then the certificate should be issued successfully
10+
11+
Scenario: Issue a certificate with a namespaced Issuer using role assumption
12+
Given I create a namespace
13+
And I create an AWSPCAIssuer with role assumption
14+
When I issue a RSA certificate
15+
Then the certificate should be issued successfully

0 commit comments

Comments
 (0)