Skip to content

Commit

Permalink
Merge branch 'master' into TheRealAmazonKendra/cli-output-off-screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Apr 5, 2022
2 parents 2cb4085 + a2ac36e commit f561378
Show file tree
Hide file tree
Showing 343 changed files with 12,309 additions and 866 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/auto-approve.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: hmarr/auto-approve-action@v2.1.0
- uses: hmarr/auto-approve-action@v2.2.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ import * as opensearch from '@aws-cdk/aws-opensearchservice';

const user = new iam.User(this, 'User');
const domain = new opensearch.Domain(this, 'Domain', {
version: opensearch.EngineVersion.OPENSEARCH_1_1,
version: opensearch.EngineVersion.OPENSEARCH_1_2,
removalPolicy: RemovalPolicy.DESTROY,
fineGrainedAccessControl: { masterUserArn: user.userArn },
encryptionAtRest: { enabled: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"EncryptionAtRestOptions": {
"Enabled": true
},
"EngineVersion": "OpenSearch_1.1",
"EngineVersion": "OpenSearch_1.2",
"LogPublishingOptions": {},
"NodeToNodeEncryptionOptions": {
"Enabled": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const app = new cdk.App();
const stack = new cdk.Stack(app, 'appsync-opensearch');
const user = new User(stack, 'User');
const domain = new opensearch.Domain(stack, 'Domain', {
version: opensearch.EngineVersion.OPENSEARCH_1_1,
version: opensearch.EngineVersion.OPENSEARCH_1_2,
removalPolicy: cdk.RemovalPolicy.DESTROY,
fineGrainedAccessControl: {
masterUserArn: user.userArn,
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-dynamodb/lib/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ export class Table extends TableBase {
attributeDefinitions: this.attributeDefinitions,
globalSecondaryIndexes: Lazy.any({ produce: () => this.globalSecondaryIndexes }, { omitEmptyArray: true }),
localSecondaryIndexes: Lazy.any({ produce: () => this.localSecondaryIndexes }, { omitEmptyArray: true }),
pointInTimeRecoverySpecification: props.pointInTimeRecovery ? { pointInTimeRecoveryEnabled: props.pointInTimeRecovery } : undefined,
pointInTimeRecoverySpecification: props.pointInTimeRecovery != null ? { pointInTimeRecoveryEnabled: props.pointInTimeRecovery } : undefined,
billingMode: this.billingMode === BillingMode.PAY_PER_REQUEST ? this.billingMode : undefined,
provisionedThroughput: this.billingMode === BillingMode.PAY_PER_REQUEST ? undefined : {
readCapacityUnits: props.readCapacity || 5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
"VpcPublicSubnet1Subnet5C2D37C4": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/18",
"VpcId": {
"Ref": "Vpc8378EB38"
},
"AvailabilityZone": "test-region-1a",
"CidrBlock": "10.0.0.0/18",
"MapPublicIpOnLaunch": true,
"Tags": [
{
Expand Down Expand Up @@ -115,11 +115,11 @@
"VpcPublicSubnet2Subnet691E08A3": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.64.0/18",
"VpcId": {
"Ref": "Vpc8378EB38"
},
"AvailabilityZone": "test-region-1b",
"CidrBlock": "10.0.64.0/18",
"MapPublicIpOnLaunch": true,
"Tags": [
{
Expand Down Expand Up @@ -180,11 +180,11 @@
"VpcPrivateSubnet1Subnet536B997A": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.128.0/18",
"VpcId": {
"Ref": "Vpc8378EB38"
},
"AvailabilityZone": "test-region-1a",
"CidrBlock": "10.0.128.0/18",
"MapPublicIpOnLaunch": false,
"Tags": [
{
Expand Down Expand Up @@ -242,11 +242,11 @@
"VpcPrivateSubnet2Subnet3788AAA1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.192.0/18",
"VpcId": {
"Ref": "Vpc8378EB38"
},
"AvailabilityZone": "test-region-1b",
"CidrBlock": "10.0.192.0/18",
"MapPublicIpOnLaunch": false,
"Tags": [
{
Expand Down Expand Up @@ -631,7 +631,11 @@
"VpcId": {
"Ref": "Vpc8378EB38"
}
}
},
"DependsOn": [
"ServiceLBPublicListenerECSGroup0CC8688C",
"ServiceLBPublicListener46709EAA"
]
}
},
"Outputs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class TestStack extends Stack {
port: 80,
});

listener.addTargets('Targets', {
const target = listener.addTargets('Targets', {
targets: [new targets.AlbTarget(svc.loadBalancer, 80)],
port: 80,
healthCheck: {
protocol: elbv2.Protocol.HTTP,
},
});
target.node.addDependency(svc.listener);

new CfnOutput(this, 'NlbEndpoint', { value: `http://${nlb.loadBalancerDnsName}` });
}
Expand Down
32 changes: 32 additions & 0 deletions packages/@aws-cdk/aws-iam/lib/policy-statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export class PolicyStatement {
private readonly condition: { [key: string]: any } = { };
private principalConditionsJson?: string;

// Hold on to those principals
private readonly _principals = new Array<IPrincipal>();

constructor(props: PolicyStatementProps = {}) {
// Validate actions
for (const action of [...props.actions || [], ...props.notActions || []]) {
Expand Down Expand Up @@ -145,6 +148,7 @@ export class PolicyStatement {
* @param principals IAM principals that will be added
*/
public addPrincipals(...principals: IPrincipal[]) {
this._principals.push(...principals);
if (Object.keys(principals).length > 0 && Object.keys(this.notPrincipal).length > 0) {
throw new Error('Cannot add \'Principals\' to policy statement if \'NotPrincipals\' have been added');
}
Expand All @@ -156,6 +160,15 @@ export class PolicyStatement {
}
}

/**
* Expose principals to allow their ARNs to be replaced by account ID strings
* in policy statements for resources policies that don't allow full account ARNs,
* such as AWS::Logs::ResourcePolicy.
*/
public get principals(): IPrincipal[] {
return [...this._principals];
}

/**
* Specify principals that is not allowed or denied access to the "NotPrincipal" section of
* a policy statement.
Expand Down Expand Up @@ -319,6 +332,25 @@ export class PolicyStatement {
this.addCondition('StringEquals', { 'sts:ExternalId': accountId });
}

/**
* Create a new `PolicyStatement` with the same exact properties
* as this one, except for the overrides
*/
public copy(overrides: PolicyStatementProps = {}) {
return new PolicyStatement({
sid: overrides.sid ?? this.sid,
effect: overrides.effect ?? this.effect,
actions: overrides.actions ?? this.action,
notActions: overrides.notActions ?? this.notAction,

principals: overrides.principals,
notPrincipals: overrides.notPrincipals,

resources: overrides.resources ?? this.resource,
notResources: overrides.notResources ?? this.notResource,
});
}

/**
* JSON-ify the policy statement
*
Expand Down
39 changes: 23 additions & 16 deletions packages/@aws-cdk/aws-iam/lib/private/merge-statements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,33 @@ import { StatementSchema, normalizeStatement, IamValue } from './postprocess-pol
export function mergeStatements(statements: StatementSchema[]): StatementSchema[] {
const compStatements = statements.map(makeComparable);

let i = 0;
while (i < compStatements.length) {
let didMerge = false;

for (let j = i + 1; j < compStatements.length; j++) {
const merged = tryMerge(compStatements[i], compStatements[j]);
if (merged) {
compStatements[i] = merged;
compStatements.splice(j, 1);
didMerge = true;
break;
// Keep trying until nothing changes anymore
while (onePass()) { /* again */ }
return compStatements.map(renderComparable);

// Do one optimization pass, return 'true' if we merged anything
function onePass() {
let ret = false;
let i = 0;
while (i < compStatements.length) {
let didMerge = false;

for (let j = i + 1; j < compStatements.length; j++) {
const merged = tryMerge(compStatements[i], compStatements[j]);
if (merged) {
compStatements[i] = merged;
compStatements.splice(j, 1);
ret = didMerge = true;
break;
}
}
}

if (!didMerge) {
i++;
if (!didMerge) {
i++;
}
}
return ret;
}

return compStatements.map(renderComparable);
}

/**
Expand Down
30 changes: 30 additions & 0 deletions packages/@aws-cdk/aws-iam/test/merge-statements.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,36 @@ test('fail merging typed and untyped principals', () => {
]);
});

test('keep merging even if it requires multiple passes', () => {
// [A, R1], [B, R1], [A, R2], [B, R2]
// -> [{A, B}, R1], [{A, B], R2]
// -> [{A, B}, {R1, R2}]
assertMerged([
new iam.PolicyStatement({
actions: ['service:A'],
resources: ['R1'],
}),
new iam.PolicyStatement({
actions: ['service:B'],
resources: ['R1'],
}),
new iam.PolicyStatement({
actions: ['service:A'],
resources: ['R2'],
}),
new iam.PolicyStatement({
actions: ['service:B'],
resources: ['R2'],
}),
], [
{
Effect: 'Allow',
Action: ['service:A', 'service:B'],
Resource: ['R1', 'R2'],
},
]);
});

function assertNoMerge(statements: iam.PolicyStatement[]) {
const app = new App();
const stack = new Stack(app, 'Stack');
Expand Down
10 changes: 5 additions & 5 deletions packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,17 @@ describe('singleton lambda', () => {

// WHEN
const invokeResult = singleton.grantInvoke(new iam.ServicePrincipal('events.amazonaws.com'));
const statement = stack.resolve(invokeResult.resourceStatement);
const statement = stack.resolve(invokeResult.resourceStatement?.toJSON());

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', {
Action: 'lambda:InvokeFunction',
Principal: 'events.amazonaws.com',
});
expect(statement.action).toEqual(['lambda:InvokeFunction']);
expect(statement.principal).toEqual({ Service: ['events.amazonaws.com'] });
expect(statement.effect).toEqual('Allow');
expect(statement.resource).toEqual([
expect(statement.Action).toEqual('lambda:InvokeFunction');
expect(statement.Principal).toEqual({ Service: 'events.amazonaws.com' });
expect(statement.Effect).toEqual('Allow');
expect(statement.Resource).toEqual([
{ 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] },
{ 'Fn::Join': ['', [{ 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] }, ':*']] },
]);
Expand Down
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-logs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ const logGroup = new logs.LogGroup(this, 'LogGroup');
logGroup.grantWrite(new iam.ServicePrincipal('es.amazonaws.com'));
```

Be aware that any ARNs or tokenized values passed to the resource policy will be converted into AWS Account IDs.
This is because CloudWatch Logs Resource Policies do not accept ARNs as principals, but they do accept
Account ID strings. Non-ARN principals, like Service principals or Any princpals, are accepted by CloudWatch.

## Encrypting Log Groups

By default, log group data is always encrypted in CloudWatch Logs. You have the
Expand Down
28 changes: 26 additions & 2 deletions packages/@aws-cdk/aws-logs/lib/log-group.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as iam from '@aws-cdk/aws-iam';
import * as kms from '@aws-cdk/aws-kms';
import { ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core';
import { Arn, ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { LogStream } from './log-stream';
import { CfnLogGroup } from './logs.generated';
Expand Down Expand Up @@ -194,15 +194,39 @@ abstract class LogGroupBase extends Resource implements ILogGroup {
/**
* Adds a statement to the resource policy associated with this log group.
* A resource policy will be automatically created upon the first call to `addToResourcePolicy`.
*
* Any ARN Principals inside of the statement will be converted into AWS Account ID strings
* because CloudWatch Logs Resource Policies do not accept ARN principals.
*
* @param statement The policy statement to add
*/
public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult {
if (!this.policy) {
this.policy = new ResourcePolicy(this, 'Policy');
}
this.policy.document.addStatements(statement);
this.policy.document.addStatements(statement.copy({
principals: statement.principals.map(p => this.convertArnPrincpalToAccountId(p)),
}));
return { statementAdded: true, policyDependable: this.policy };
}

private convertArnPrincpalToAccountId(principal: iam.IPrincipal) {
if (principal.principalAccount) {
// we use ArnPrincipal here because the constructor inserts the argument
// into the template without mutating it, which means that there is no
// ARN created by this call.
return new iam.ArnPrincipal(principal.principalAccount);
}

if (principal instanceof iam.ArnPrincipal) {
const parsedArn = Arn.split(principal.arn, ArnFormat.SLASH_RESOURCE_NAME);
if (parsedArn.account) {
return new iam.ArnPrincipal(parsedArn.account);
}
}

return principal;
}
}

/**
Expand Down
Loading

0 comments on commit f561378

Please sign in to comment.