-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ack addon must support inline policies for EKS
The EKS ack controller doesn't have a recommended managed policy, only an inline one, and the currently provided managed policy in blueprints doesn't seem to give any eks permissions, nor does any other managed policy seem to be appropriate. The best option is to support inline policies. There may be other ack controllers with similar issues, but EKS is the one I'm aware of. Signed-off-by: Jack Kleeman <[email protected]>
- Loading branch information
1 parent
cc7aae3
commit 821ff04
Showing
2 changed files
with
149 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,122 +1,135 @@ | ||
import { ManagedPolicy } from 'aws-cdk-lib/aws-iam'; | ||
import { Construct } from 'constructs'; | ||
import merge from "ts-deepmerge"; | ||
import { ClusterInfo, Values } from "../../spi"; | ||
import "reflect-metadata"; | ||
import { createNamespace, setPath, supportsX86 } from "../../utils"; | ||
import { HelmAddOn, HelmAddOnProps, HelmAddOnUserProps } from "../helm-addon"; | ||
import { AckServiceName, serviceMappings } from './serviceMappings'; | ||
|
||
export * from "./serviceMappings"; | ||
|
||
/** | ||
* User provided option for the Helm Chart | ||
*/ | ||
export interface AckAddOnProps extends HelmAddOnUserProps { | ||
/** | ||
* Required identified, must be unique within the parent stack scope. | ||
*/ | ||
id?: string; | ||
/** | ||
* Default Service Name | ||
* @default iam | ||
*/ | ||
serviceName: AckServiceName; | ||
/** | ||
* Managed IAM Policy of the ack controller | ||
* @default IAMFullAccess | ||
*/ | ||
managedPolicyName?: string; | ||
/** | ||
* To Create Namespace using CDK. This should be done only for the first time. | ||
*/ | ||
createNamespace?: boolean; | ||
/** | ||
* To create Service Account | ||
*/ | ||
saName?: string; | ||
} | ||
|
||
/** | ||
* Default props to be used when creating the Helm chart | ||
*/ | ||
const defaultProps: AckAddOnProps = { | ||
namespace: "ack-system", | ||
values: {}, | ||
createNamespace: true, | ||
serviceName: AckServiceName.IAM, | ||
id: "iam-ack" | ||
}; | ||
|
||
/** | ||
* Main class to instantiate the Helm chart | ||
*/ | ||
@Reflect.metadata("ordered", true) | ||
@supportsX86 | ||
export class AckAddOn extends HelmAddOn { | ||
|
||
readonly options: AckAddOnProps; | ||
readonly id? : string; | ||
|
||
constructor(props?: AckAddOnProps) { | ||
super(populateDefaults(defaultProps, props) as HelmAddOnProps); | ||
this.options = this.props as AckAddOnProps; | ||
this.id = this.options.id; | ||
} | ||
|
||
|
||
deploy(clusterInfo: ClusterInfo): Promise<Construct> { | ||
const cluster = clusterInfo.cluster; | ||
|
||
const sa = cluster.addServiceAccount(`${this.options.chart}-sa`, { | ||
namespace: this.options.namespace, | ||
name: this.options.saName, | ||
}); | ||
|
||
let values: Values = populateValues(this.options,cluster.stack.region); | ||
values = merge(values, this.props.values ?? {}); | ||
|
||
if(this.options.createNamespace == true){ | ||
// Let CDK Create the Namespace | ||
const namespace = createNamespace(this.options.namespace! , cluster); | ||
sa.node.addDependency(namespace); | ||
} | ||
|
||
sa.role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName(this.options.managedPolicyName!)); | ||
const chart = this.addHelmChart(clusterInfo, values); | ||
chart.node.addDependency(sa); | ||
return Promise.resolve(chart); | ||
} | ||
} | ||
|
||
/** | ||
* populateValues populates the appropriate values used to customize the Helm chart | ||
* @param helmOptions User provided values to customize the chart | ||
*/ | ||
function populateValues(helmOptions: AckAddOnProps, awsRegion: string): Values { | ||
const values = helmOptions.values ?? {}; | ||
setPath(values, "aws.region", awsRegion); | ||
setPath(values,"serviceAccount.create", false); | ||
setPath(values,"serviceAccount.name", helmOptions.saName); | ||
return values; | ||
} | ||
|
||
/** | ||
* populate parameters passed or the default values from service Mappings. | ||
*/ | ||
function populateDefaults(defaultProps: AckAddOnProps, props?: AckAddOnProps): AckAddOnProps { | ||
let tempProps : Partial<AckAddOnProps> = {...props ?? {}}; // since props may be empty | ||
tempProps.id = tempProps.id ?? defaultProps.id; | ||
tempProps.serviceName = tempProps.serviceName ?? defaultProps.serviceName; | ||
tempProps.name = tempProps.name ?? serviceMappings[tempProps.serviceName!]!.chart; | ||
tempProps.namespace = tempProps.namespace ?? defaultProps.namespace; | ||
tempProps.chart = tempProps.chart ?? serviceMappings[tempProps.serviceName!]?.chart; | ||
tempProps.version = tempProps.version ?? serviceMappings[tempProps.serviceName!]?.version; | ||
const repositoryUrl = "oci://public.ecr.aws/aws-controllers-k8s"; | ||
tempProps.release = tempProps.release ?? tempProps.chart; | ||
tempProps.repository = tempProps.repository ?? `${repositoryUrl}/${tempProps.name}`; | ||
tempProps.managedPolicyName = tempProps.managedPolicyName ?? serviceMappings[tempProps.serviceName!]?.managedPolicyName; | ||
tempProps.createNamespace = tempProps.createNamespace ?? defaultProps.createNamespace; | ||
tempProps.saName = tempProps.saName ?? `${tempProps.chart}-sa`; | ||
return tempProps as AckAddOnProps; | ||
} | ||
import { ManagedPolicy, Policy, PolicyStatement } from 'aws-cdk-lib/aws-iam'; | ||
import { Construct } from 'constructs'; | ||
import merge from "ts-deepmerge"; | ||
import { ClusterInfo, Values } from "../../spi"; | ||
import "reflect-metadata"; | ||
import { createNamespace, setPath, supportsX86 } from "../../utils"; | ||
import { HelmAddOn, HelmAddOnProps, HelmAddOnUserProps } from "../helm-addon"; | ||
import { AckServiceName, serviceMappings } from './serviceMappings'; | ||
|
||
export * from "./serviceMappings"; | ||
|
||
/** | ||
* User provided option for the Helm Chart | ||
*/ | ||
export interface AckAddOnProps extends HelmAddOnUserProps { | ||
/** | ||
* Required identified, must be unique within the parent stack scope. | ||
*/ | ||
id?: string; | ||
/** | ||
* Default Service Name | ||
* @default iam | ||
*/ | ||
serviceName: AckServiceName; | ||
/** | ||
* Managed IAM Policy of the ack controller | ||
* @default IAMFullAccess | ||
*/ | ||
managedPolicyName?: string; | ||
/** | ||
* Inline IAM Policy for the ack controller | ||
* @default undefined | ||
*/ | ||
inlinePolicyStatements?: PolicyStatement[]; | ||
/** | ||
* To Create Namespace using CDK. This should be done only for the first time. | ||
*/ | ||
createNamespace?: boolean; | ||
/** | ||
* To create Service Account | ||
*/ | ||
saName?: string; | ||
} | ||
|
||
/** | ||
* Default props to be used when creating the Helm chart | ||
*/ | ||
const defaultProps: AckAddOnProps = { | ||
namespace: "ack-system", | ||
values: {}, | ||
createNamespace: true, | ||
serviceName: AckServiceName.IAM, | ||
id: "iam-ack" | ||
}; | ||
|
||
/** | ||
* Main class to instantiate the Helm chart | ||
*/ | ||
@Reflect.metadata("ordered", true) | ||
@supportsX86 | ||
export class AckAddOn extends HelmAddOn { | ||
|
||
readonly options: AckAddOnProps; | ||
readonly id? : string; | ||
|
||
constructor(props?: AckAddOnProps) { | ||
super(populateDefaults(defaultProps, props) as HelmAddOnProps); | ||
this.options = this.props as AckAddOnProps; | ||
this.id = this.options.id; | ||
} | ||
|
||
|
||
deploy(clusterInfo: ClusterInfo): Promise<Construct> { | ||
const cluster = clusterInfo.cluster; | ||
|
||
const sa = cluster.addServiceAccount(`${this.options.chart}-sa`, { | ||
namespace: this.options.namespace, | ||
name: this.options.saName, | ||
}); | ||
|
||
let values: Values = populateValues(this.options,cluster.stack.region); | ||
values = merge(values, this.props.values ?? {}); | ||
|
||
if(this.options.createNamespace == true){ | ||
// Let CDK Create the Namespace | ||
const namespace = createNamespace(this.options.namespace! , cluster); | ||
sa.node.addDependency(namespace); | ||
} | ||
|
||
if (this.options.managedPolicyName) { | ||
sa.role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName(this.options.managedPolicyName!)); | ||
} | ||
if (this.options.inlinePolicyStatements && this.options.inlinePolicyStatements.length > 0) { | ||
sa.role.attachInlinePolicy(new Policy(cluster.stack, "inline-policy", { | ||
statements: this.options.inlinePolicyStatements | ||
})); | ||
} | ||
const chart = this.addHelmChart(clusterInfo, values); | ||
chart.node.addDependency(sa); | ||
return Promise.resolve(chart); | ||
} | ||
} | ||
|
||
/** | ||
* populateValues populates the appropriate values used to customize the Helm chart | ||
* @param helmOptions User provided values to customize the chart | ||
*/ | ||
function populateValues(helmOptions: AckAddOnProps, awsRegion: string): Values { | ||
const values = helmOptions.values ?? {}; | ||
setPath(values, "aws.region", awsRegion); | ||
setPath(values,"serviceAccount.create", false); | ||
setPath(values,"serviceAccount.name", helmOptions.saName); | ||
return values; | ||
} | ||
|
||
/** | ||
* populate parameters passed or the default values from service Mappings. | ||
*/ | ||
function populateDefaults(defaultProps: AckAddOnProps, props?: AckAddOnProps): AckAddOnProps { | ||
let tempProps : Partial<AckAddOnProps> = {...props ?? {}}; // since props may be empty | ||
tempProps.id = tempProps.id ?? defaultProps.id; | ||
tempProps.serviceName = tempProps.serviceName ?? defaultProps.serviceName; | ||
tempProps.name = tempProps.name ?? serviceMappings[tempProps.serviceName!]!.chart; | ||
tempProps.namespace = tempProps.namespace ?? defaultProps.namespace; | ||
tempProps.chart = tempProps.chart ?? serviceMappings[tempProps.serviceName!]?.chart; | ||
tempProps.version = tempProps.version ?? serviceMappings[tempProps.serviceName!]?.version; | ||
const repositoryUrl = "oci://public.ecr.aws/aws-controllers-k8s"; | ||
tempProps.release = tempProps.release ?? tempProps.chart; | ||
tempProps.repository = tempProps.repository ?? `${repositoryUrl}/${tempProps.name}`; | ||
tempProps.managedPolicyName = tempProps.managedPolicyName ?? serviceMappings[tempProps.serviceName!]?.managedPolicyName; | ||
tempProps.inlinePolicyStatements = tempProps.inlinePolicyStatements ?? serviceMappings[tempProps.serviceName!]?.inlinePolicyStatements; | ||
tempProps.createNamespace = tempProps.createNamespace ?? defaultProps.createNamespace; | ||
tempProps.saName = tempProps.saName ?? `${tempProps.chart}-sa`; | ||
return tempProps as AckAddOnProps; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters