Skip to content

Commit

Permalink
Fixing merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
elamaran11 committed Mar 15, 2023
2 parents f7c7213 + 06786fa commit 15c8227
Show file tree
Hide file tree
Showing 19 changed files with 441 additions and 91 deletions.
10 changes: 5 additions & 5 deletions docs/addons/efs-csi-driver.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# EFS CSI Driver Amazon EKS Add-on

The `EFS CSI Driver Amazon EKS Add-on` provides a CSI interface that allows Kubernetes clusters running on AWS to manage the lifecycle of Amazon EFS volumes for persistent storage.
EFS CSI driver supports both dynamic and static provisioning of storage
EFS CSI driver supports both dynamic and static provisioning of storage.

A couple of things to note:

Expand All @@ -12,7 +12,7 @@ For more information on the driver, please review the [user guide](https://docs.

## Prerequisites

- The EFS file system itself must be created in AWS separately as the driver uses the EFS for storage, but it does not create it.
- The EFS file system itself must be created in AWS separately as the driver uses the EFS for storage, but it does not create it. You can create an EFS file system using the `CreateEfsFileSystemProvider`, e.g.: `.resourceProvider("efs-file-system", new CreateEfsFileSystemProvider('efs-file-system'))`

## Usage

Expand All @@ -35,7 +35,7 @@ const blueprint = blueprints.EksBlueprint.builder()
- `version`: Version of the EFS CSI Driver add-on to be installed. Version 2.2.3 will be installed by default if a value is not provided
- `replicaCount`: Number of replicas to be deployed. If not provided, two replicas will be deployed. Note that the number of replicas
should be less than or equal to the number of nodes in the cluster otherwise some pods will be left of pending state

- `kmsKeys`: List of KMS keys used for encryption-at-rest, so that the IAM policy can be updated to allow the EFS CSI driver to access the keys

## Validation

Expand All @@ -51,8 +51,8 @@ efs-csi-node-2c29j 3/3 Running 0 155m

```

Additionally, the [driver documentation](https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html) shows how to create an EFS file system to test the driver
Additionally, the [driver documentation](https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html) shows how to create an EFS file system to test the driver

## Functionality

Applies the EFS CSI Driver add-on to an Amazon EKS cluster.
Applies the EFS CSI Driver add-on to an Amazon EKS cluster.
24 changes: 13 additions & 11 deletions docs/resource-providers/index.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
# Resource Providers

## Terminology
## Terminology

**Resource**
A resource is a CDK construct that implements `IResource` interface from `aws-cdk-lib` which is a generic interface for any AWS resource. An example of a resource could be a hosted zone in Route53 [`IHostedZone`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html), an ACM certificate [`ICertificate`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager.ICertificate.html), a VPC or even a DynamoDB table which could be leveraged either in add-ons or teams.

**ResourceProvider**
A resource provider is a core Blueprints concept that enables customers to supply resources for add-ons, teams and/or post-deployment steps. Resources may be imported (e.g., if created outside of the platform) or created with the blueprint.
A resource provider is a core Blueprints concept that enables customers to supply resources for add-ons, teams and/or post-deployment steps. Resources may be imported (e.g., if created outside of the platform) or created with the blueprint.

## Use Cases

`ClusterAddOn` and `Team` implementations require AWS resources that can be shared across several constructs. For example, `ExternalDnsAddOn` requires an array of hosted zones that will be used for integration with Route53. `NginxAddOn` requires a certificate and hosted zone (for DNS validation) in order to use TLS termination. VPC may be used inside add-ons and team constructs to look up VPC CIDR and subnets.
`ClusterAddOn` and `Team` implementations require AWS resources that can be shared across several constructs. For example, `ExternalDnsAddOn` requires an array of hosted zones that will be used for integration with Route53. `NginxAddOn` requires a certificate and hosted zone (for DNS validation) in order to use TLS termination. VPC may be used inside add-ons and team constructs to look up VPC CIDR and subnets.

The Blueprints framework provides ability to register a resource provider under an arbitrary name and make it available in the resource context, which is available to all add-ons and teams. With this capability, customers can either use existing resource providers or create their own and reference the provided resources inside add-ons, teams or other resource providers.
The Blueprints framework provides ability to register a resource provider under an arbitrary name and make it available in the resource context, which is available to all add-ons and teams. With this capability, customers can either use existing resource providers or create their own and reference the provided resources inside add-ons, teams or other resource providers.

Resource providers may depend on resources provided by other resource providers. For example, `CertificateResourceProvider` relies on a hosted zone resource, which is expected to be supplied by another provider.

Example use cases:

1. As a platform user, I must create a VPC using my enterprise standards and leverage it for the EKS Blueprint. Solution: create an implementation of `ResourceProvider<IVpc>` (or leverage an existing one) and register it with the blueprint (see Usage).

2. As a platform user, I need to use an existing hosted zone for all external DNS names used with ingress objects of my workloads. Solution: use a predefined `ImportHostedZoneProvider` or `LookupHostedZoneProvider` to reference the existing hosted zone.
2. As a platform user, I need to use an existing hosted zone for all external DNS names used with ingress objects of my workloads. Solution: use a predefined `ImportHostedZoneProvider` or `LookupHostedZoneProvider` to reference the existing hosted zone.

3. As a platform user, I need to create an S3 bucket and use it in one or more `Team` implementations. Solution: create an implementation for an S3 Bucket resource provider and use the supplied resource inside teams.
3. As a platform user, I need to create an S3 bucket and use it in one or more `Team` implementations. Solution: create an implementation for an S3 Bucket resource provider and use the supplied resource inside teams.

## Contracts

Expand Down Expand Up @@ -119,7 +119,6 @@ export class ClusterInfo {
}
```


## Usage

**Registering Resource Providers for a Blueprint**
Expand All @@ -133,13 +132,15 @@ blueprints.EksBlueprint.builder()
// Specify VPC for the cluster (if not set, a new VPC will be provisioned as per EKS Best Practices)
.resourceProvider(GlobalResources.VPC, new VpcProvider(myVpcId)
// Specify KMS Key as cluster secrets encryption key
.resourceProvider(GlobalResources.KmsKey, new KmsKeyProvider('my-alias-name')
.resourceProvider(GlobalResources.KmsKey, new CreateKmsKeyProvider('my-alias-name')
// Register hosted zone and give it a name of GlobalResources.HostedZone
.resourceProvider(GlobalResources.HostedZone, new ImportHostedZoneProvider('hosted-zone-id1', 'my.domain.com'))
.resourceProvider("internal-hosted-zone", new ImportHostedZoneProvider('hosted-zone-id2', 'myinternal.domain.com'))
// Register certificate GlobalResources.Certificate name and reference the hosted zone registered in the previous step
.resourceProvider(GlobalResources.Certificate, new CreateCertificateProvider('domain-wildcard-cert', '*.my.domain.com', GlobalResources.HostedZone))
.resourceProvider("private-ca", new CreateCertificateProvider('internal-wildcard-cert', '*.myinternal.domain.com', "internal-hosted-zone"))
// Create EFS file system and register it under the name of efs-file-system
.resourceProvider("efs-file-system", new CreateEfsFileSystemProvider('efs-file-system'))
.addOns(new AwsLoadBalancerControllerAddOn())
// Use hosted zone for External DNS
.addOns(new ExternalDnsAddOn({hostedZoneResources: [GlobalResources.HostedZone]}))
Expand Down Expand Up @@ -173,9 +174,10 @@ blueprints.EksBlueprint.builder()
.teams(...)
.build(app, 'stack-with-resource-providers');
```
## Using Resource Providers with CDK Constructs
Some constructs used in the `EKSBlueprint` stack are standard CDK constructs that accept CDK resources.
Some constructs used in the `EKSBlueprint` stack are standard CDK constructs that accept CDK resources.
For example, `GenericClusterProvider` (which is the basis for all cluster providers) allows passing resources like `IRole`, `SecurityGroup` and other properties that customers may find inconvenient to define with a builder pattern.
Expand All @@ -201,7 +203,7 @@ blueprints.EksBlueprint.builder()
}
```
Example with a named resource:
Example with a named resource:
```typescript
const clusterProvider = new blueprints.GenericClusterProvider({
Expand Down Expand Up @@ -244,6 +246,7 @@ blueprints.EksBlueprint.builder()
```
4. Use the resource inside a custom add-on:
```typescript
class MyCustomAddOn implements blueprints.ClusterAddOn {
deploy(clusterInfo: ClusterInfo): void | Promise<cdk.Construct> {
Expand All @@ -253,4 +256,3 @@ class MyCustomAddOn implements blueprints.ClusterAddOn {
}

```
8 changes: 7 additions & 1 deletion examples/blueprint-construct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,12 @@ export default class BlueprintConstruct {
],
}
),
new blueprints.addons.EfsCsiDriverAddOn({replicaCount: 1}),
new blueprints.addons.EfsCsiDriverAddOn({
replicaCount: 1,
kmsKeys: [
blueprints.getResource( context => new kms.Key(context.scope, "efs-csi-driver-key", { alias: "efs-csi-driver-key"})),
],
}),
new blueprints.addons.KedaAddOn({
podSecurityContextFsGroup: 1001,
securityContextRunAsGroup: 1001,
Expand All @@ -164,6 +169,7 @@ export default class BlueprintConstruct {
new blueprints.EmrEksAddOn(),
new blueprints.AwsBatchAddOn(),
new blueprints.UpboundUniversalCrossplaneAddOn(),
new blueprints.AwsForFluentBitAddOn(),
];

// Instantiated to for helm version check.
Expand Down
22 changes: 16 additions & 6 deletions lib/addons/aws-for-fluent-bit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export interface AwsForFluentBitAddOnProps extends HelmAddOnUserProps {
/**
* Iam policies for the add-on.
*/
iamPolicies?: PolicyStatement[]
iamPolicies?: PolicyStatement[],

/**
* Create Namespace with the provided one (will not if namespace is kube-system)
*/
createNamespace?: boolean
}
/**
* Default props for the add-on.
Expand All @@ -21,9 +26,10 @@ const defaultProps: AwsForFluentBitAddOnProps = {
name: 'fluent-bit',
chart: 'aws-for-fluent-bit',
release: "blueprints-addon-aws-for-fluent-bit",
version: '0.1.11',
version: '0.1.23',
repository: 'https://aws.github.io/eks-charts',
namespace: 'kube-system',
createNamespace: false,
values: {}
};

Expand All @@ -45,10 +51,7 @@ export class AwsForFluentBitAddOn extends HelmAddOn {

deploy(clusterInfo: ClusterInfo): Promise<Construct> {
const cluster = clusterInfo.cluster;

// Create the FluentBit namespace.
const namespace = this.options.namespace;
createNamespace(this.options.namespace!, cluster, true);
const namespace = this.options.namespace!;

// Create the FluentBut service account.
const serviceAccountName = 'aws-for-fluent-bit-sa';
Expand All @@ -57,6 +60,12 @@ export class AwsForFluentBitAddOn extends HelmAddOn {
namespace: namespace
});

// Create namespace
if (this.options.createNamespace) {
const ns = createNamespace(namespace, cluster, true);
sa.node.addDependency(ns);
}

// Apply additional IAM policies to the service account.
const policies = this.options.iamPolicies || [];
policies.forEach((policy: PolicyStatement) => sa.addToPrincipalPolicy(policy));
Expand All @@ -71,6 +80,7 @@ export class AwsForFluentBitAddOn extends HelmAddOn {
};

const helmChart = this.addHelmChart(clusterInfo, values);
helmChart.node.addDependency(sa);
return Promise.resolve(helmChart);
}
}
2 changes: 1 addition & 1 deletion lib/addons/coredns/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class CoreDnsAddOn extends CoreAddOn {
constructor(version?: string) {
super({
addOnName: "coredns",
version: version ?? "v1.8.7-eksbuild.4",
version: version ?? "v1.9.3-eksbuild.2",
saName: "coredns"
});
}
Expand Down
2 changes: 1 addition & 1 deletion lib/addons/ebs-csi-driver/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface EbsCsiDriverAddOnProps {
*/
const defaultProps = {
addOnName: "aws-ebs-csi-driver",
version: "v1.16.0-eksbuild.1",
version: "v1.16.1-eksbuild.1",
saName: "ebs-csi-controller-sa",
};

Expand Down
104 changes: 72 additions & 32 deletions lib/addons/efs-csi-driver/iam-policy.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,77 @@
export const EfsDriverPolicyDocument = () => {
return {
"Version": "2012-10-17",
"Statement": [
import * as kms from "aws-cdk-lib/aws-kms";

interface Statement {
Effect: string;
Action: string | string[];
Resource: string | string[];
Condition?: {
StringEquals?: { [key: string]: string[] | string };
StringLike?: { [key: string]: string };
Bool?: { [key: string]: string };
};
}

export function getEfsDriverPolicyStatements(
kmsKeys?: kms.Key[]
): Statement[] {
const result: Statement[] = [
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:DescribeAccessPoints",
"elasticfilesystem:DescribeFileSystems"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:CreateAccessPoint"
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:RequestTag/efs.csi.aws.com/cluster": "true"
}
}
},
{
"Effect": "Allow",
"Action": "elasticfilesystem:DeleteAccessPoint",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/efs.csi.aws.com/cluster": "true"
}
}
}
];
if (kmsKeys) {
const kmsKeysArns = kmsKeys.map((k) => k.keyArn);
const kmsPolicy: Statement[] = [
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:DescribeAccessPoints",
"elasticfilesystem:DescribeFileSystems"
],
"Resource": "*"
Effect: "Allow",
Action: ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"],
Resource: kmsKeysArns,
Condition: {
Bool: {
"kms:GrantIsForAWSResource": "true",
},
},
},
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:CreateAccessPoint"
Effect: "Allow",
Action: [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:RequestTag/efs.csi.aws.com/cluster": "true"
}
}
Resource: kmsKeysArns,
},
{
"Effect": "Allow",
"Action": "elasticfilesystem:DeleteAccessPoint",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/efs.csi.aws.com/cluster": "true"
}
}
}
]
};
};
];
result.push(...kmsPolicy);
}
return result;
}
9 changes: 7 additions & 2 deletions lib/addons/efs-csi-driver/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Construct } from "constructs";
import {ClusterInfo, Values} from "../../spi";
import { HelmAddOn, HelmAddOnUserProps } from "../helm-addon";
import { EfsDriverPolicyDocument } from "./iam-policy";
import { getEfsDriverPolicyStatements } from "./iam-policy";
import { registries } from "../../utils/registry-utils";
import * as iam from "aws-cdk-lib/aws-iam";
import {setPath} from "../../utils";
import * as kms from "aws-cdk-lib/aws-kms";


const EFS_CSI_DRIVER = "aws-efs-csi-driver";
Expand All @@ -25,6 +26,10 @@ export interface EfsCsiDriverProps extends HelmAddOnUserProps {
* pods will be left of pending state
*/
replicaCount?: number
/**
* List of KMS keys to be used for encryption
*/
kmsKeys?: kms.Key[];

}

Expand Down Expand Up @@ -56,7 +61,7 @@ export class EfsCsiDriverAddOn extends HelmAddOn {
name: EFS_CSI_CONTROLLER_SA,
namespace: this.options.namespace,
});
EfsDriverPolicyDocument().Statement.forEach((statement) => {
getEfsDriverPolicyStatements(this.options?.kmsKeys).forEach((statement) => {
serviceAccount.addToPrincipalPolicy(iam.PolicyStatement.fromJson(statement));
});

Expand Down
Loading

0 comments on commit 15c8227

Please sign in to comment.