Skip to content

Commit 24c3afc

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 24c3afc

File tree

14 files changed

+121
-26
lines changed

14 files changed

+121
-26
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ volumes:
145145
secretName: cert
146146
```
147147

148+
#### Cross Account Assume Role
149+
150+
You can configure the AWS Private CA issuer to assume an IAM role before making AWS Private CA API calls. This method provides flexibility for various authentication scenarios and is an alternative to AWS Resource Access Manager (RAM) sharing for cross-account use cases.
151+
152+
When you specify a role in the `role` field, the issuer assumes that role using AWS Security Token Service (STS) before making AWS Private CA API calls.
153+
154+
Example:
155+
```
156+
apiVersion: awspca.cert-manager.io/v1beta1
157+
kind: AWSPCAClusterIssuer
158+
metadata:
159+
name: example
160+
spec:
161+
arn: <some-pca-arn>
162+
role: <some-role-arn>
163+
region: <some-region>
164+
```
165+
148166
## Supported workflows
149167

150168
AWS Private Certificate Authority(PCA) Issuer Plugin supports the following integrations and use cases:

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: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"time"
99

1010
"github.com/aws/aws-sdk-go-v2/aws"
11-
"github.com/aws/aws-sdk-go-v2/aws/arn"
1211
"github.com/aws/aws-sdk-go-v2/config"
1312
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
1413
"github.com/aws/aws-sdk-go-v2/service/acmpca"
@@ -296,7 +295,7 @@ func getAccountID(ctx context.Context, cfg aws.Config) string {
296295
return *callerID.Account
297296
}
298297

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

302301
callerID, callerErr := stsClient.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
@@ -305,12 +304,7 @@ func getPartition(ctx context.Context, cfg aws.Config) string {
305304
panic(callerErr.Error())
306305
}
307306

308-
parsedArn, parseErr := arn.Parse(*callerID.Arn)
309-
if parseErr != nil {
310-
return "aws"
311-
}
312-
313-
return parsedArn.Partition
307+
return callerID
314308
}
315309

316310
func assumeRole(ctx context.Context, cfg aws.Config, roleName string, region string) aws.Config {

e2e/awspcaissuer_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/aws/aws-sdk-go-v2/aws"
13+
"github.com/aws/aws-sdk-go-v2/aws/arn"
1314
"github.com/aws/aws-sdk-go-v2/config"
1415
"github.com/cert-manager/aws-privateca-issuer/pkg/api/v1beta1"
1516
clientV1beta1 "github.com/cert-manager/aws-privateca-issuer/pkg/clientset/v1beta1"
@@ -31,7 +32,7 @@ type TestContext struct {
3132
xaCfg aws.Config
3233
caArns map[string]string
3334

34-
region, partition, accessKey, secretKey, endEntityResourceShareArn, subordinateCaResourceShareArn, userName, policyArn string
35+
region, partition, accessKey, secretKey, endEntityResourceShareArn, subordinateCaResourceShareArn, userName, policyArn, roleToAssume string
3536
}
3637

3738
// These are variables specific to each test
@@ -111,7 +112,19 @@ func InitializeTestSuite(suiteCtx *godog.TestSuiteContext) {
111112
panic(cfgErr.Error())
112113
}
113114

114-
testContext.partition = getPartition(ctx, cfg)
115+
callerID := getCallerIdentity(ctx, cfg)
116+
117+
parsedArn, parseErr := arn.Parse(*callerID.Arn)
118+
if parseErr != nil {
119+
panic("Failed to parse caller identity ARN: " + parseErr.Error())
120+
}
121+
122+
testContext.partition = parsedArn.Partition
123+
124+
testContext.roleToAssume = fmt.Sprintf("arn:%s:iam::%s:role/IssuerTestRole-test-us-east-1", testContext.partition, *callerID.Account)
125+
if roleToAssumeOverride, exists := os.LookupEnv("ROLE_TO_ASSUME_OVERRIDE"); exists {
126+
testContext.roleToAssume = roleToAssumeOverride
127+
}
115128

116129
testContext.iclient, err = clientV1beta1.NewForConfig(clientConfig)
117130

@@ -217,8 +230,10 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
217230
ctx.Step(`^I create a namespace`, issuerContext.createNamespace)
218231
ctx.Step(`^I create a Secret with keys ([A-Za-z_]+) and ([A-Za-z_]+) for my AWS credentials$`, issuerContext.createSecret)
219232
ctx.Step(`^I create an AWSPCAClusterIssuer using a (RSA|ECDSA|XA) CA$`, issuerContext.createClusterIssuer)
233+
ctx.Step(`^I create an AWSPCAClusterIssuer with role assumption$`, issuerContext.createClusterIssuerWithRole)
220234
ctx.Step(`^I delete the AWSPCAClusterIssuer$`, issuerContext.deleteClusterIssuer)
221235
ctx.Step(`^I create an AWSPCAIssuer using a (RSA|ECDSA|XA) CA$`, issuerContext.createNamespaceIssuer)
236+
ctx.Step(`^I create an AWSPCAIssuer with role assumption$`, issuerContext.createNamespaceIssuerWithRole)
222237
ctx.Step(`^I issue a (SHORT_VALIDITY|RSA|ECDSA|CA) certificate$`, issuerContext.issueCertificate)
223238
ctx.Step(`^the certificate should be issued successfully$`, issuerContext.verifyCertificateIssued)
224239
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 = testContext.roleToAssume
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{

0 commit comments

Comments
 (0)