Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed added deny iam policy when user opt disable log for a function #8561

Merged
merged 3 commits into from Dec 1, 2020

Conversation

as19ish
Copy link
Contributor

@as19ish as19ish commented Nov 29, 2020

There is no way to disable the CloudWatch logs for a lambda function. One workaround is you can add the policy to your role to disable the CloudWatch logs.

I have added deny policy for that specific lamda so as per now by default all function have logs:PutLogEvents permission when there is disableLogs opt to true we are adding deny policy statement for that function

Closes: #8554

@codecov-io
Copy link

codecov-io commented Nov 29, 2020

Codecov Report

Merging #8561 (ff2a89f) into master (3808471) will increase coverage by 0.01%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #8561      +/-   ##
==========================================
+ Coverage   87.27%   87.28%   +0.01%     
==========================================
  Files         256      256              
  Lines        9516     9524       +8     
==========================================
+ Hits         8305     8313       +8     
  Misses       1211     1211              
Impacted Files Coverage Δ
lib/plugins/aws/package/lib/mergeIamTemplates.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3808471...ff2a89f. Read the comment docs.

Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@as19ish Thank you! Please see my comment

this.serverless.service.provider.compiledCloudFormationTemplate.Resources[
this.provider.naming.getRoleLogicalId()
].Properties.Policies[0].PolicyDocument.Statement.push({
Effect: 'Deny',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be good enough to just not add 'Allow' policy? I believe that's all needed (by default access is denied)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@medikoo As serverless by default allow logs, so I think if we make by default access is denied so this makes more complicate the scenario. Let me know what u think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@as19ish What I meant that we should disable access simply by removing "Allow" rules, and not by by replacing them with "Deny" rules (they're effect-less, as they do no override anything)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@medikoo

I think there is some misunderstanding, I m explaining the whole problem.

By default, we are allowing lambda execution role to this permission

  1. logs:CreateLogStream
  2. logs:CreateLogGroup
  3. logs:PutLogEvents

Note: BY USING WILDCARD CHARACTER

"Statement": [
        {
            "Action": [
                "logs:CreateLogStream",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:188267231256:log-group:/aws/lambda/serverless-dev*:*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:us-east-1:188267231256:log-group:/aws/lambda/serverless-dev*:*:*"
            ],
            "Effect": "Allow"
        }
    ]

Now the main problem here how can we deny to specific lambda to do not put logs and also by default all lambda has the same lambda execution role.

So here what i'm doing is adding a new statement that denies for put logs for a specific function (full ARN not using a wildcard) as per the Principle of Least Privilege

{
            "Action": "logs:PutLogEvents",
            "Resource": [
                "arn:aws:logs:us-east-1:188267231256:log-group:/aws/lambda/serverless-dev-hello:*"
            ],
            "Effect": "Deny"
}

I m a little confused here. Can we do it in a better way?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@as19ish ah, indeed, thanks for explanations. I forgot that in common cases we use wildcards, and indeed for this, we'd need to deny the assigned rights.

Still it'll be good to integrate it better with logic which generates "Allow" rights, e.g. we should not create "Deny" rule, for functions not expressed by canonical naming (we should just prevent generation of "Allow" rights for them)

Therefore I would cover this in this part of logic:

this.serverless.service.getAllFunctions().forEach(functionName => {
const { name: resolvedFunctionName } = this.serverless.service.getFunction(functionName);
if (!resolvedFunctionName || resolvedFunctionName.startsWith(canonicalFunctionNamePrefix)) {
hasOneOrMoreCanonicallyNamedFunctions = true;
return;
}
const customFunctionNamelogGroupsPrefix = this.provider.naming.getLogGroupName(
resolvedFunctionName
);
policyDocumentStatements[0].Resource.push({
'Fn::Sub':
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
`:log-group:${customFunctionNamelogGroupsPrefix}:*`,
});
policyDocumentStatements[1].Resource.push({
'Fn::Sub':
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
`:log-group:${customFunctionNamelogGroupsPrefix}:*:*`,
});
});
if (hasOneOrMoreCanonicallyNamedFunctions) {
// Ensure general policies for functions with default name resolution
policyDocumentStatements[0].Resource.push({
'Fn::Sub':
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
`:log-group:${logGroupsPrefix}*:*`,
});
policyDocumentStatements[1].Resource.push({
'Fn::Sub':
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
`:log-group:${logGroupsPrefix}*:*:*`,
});
}

  1. For non canonical named functions, do not create "Allow" rights
  2. Group names of all disabled canonically named functions, and generate "Deny" rights in scope of this condition:
    if (hasOneOrMoreCanonicallyNamedFunctions) {
    // Ensure general policies for functions with default name resolution
    policyDocumentStatements[0].Resource.push({
    'Fn::Sub':
    'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
    `:log-group:${logGroupsPrefix}*:*`,
    });
    policyDocumentStatements[1].Resource.push({
    'Fn::Sub':
    'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}' +
    `:log-group:${logGroupsPrefix}*:*:*`,
    });
    }

@as19ish
Copy link
Contributor Author

as19ish commented Nov 30, 2020

@medikoo Have a look. I just tried to incorporate your comment. Let me know if anything I missed.

Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@as19ish Thank you! It look really good. I've proposed one final improvement we can do

const { name: resolvedFunctionName } = this.serverless.service.getFunction(functionName);
const {
name: resolvedFunctionName,
disableLogs: isDisableLogsOpt,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's name this var areLogsDisabled

if (!resolvedFunctionName || resolvedFunctionName.startsWith(canonicalFunctionNamePrefix)) {
if (isDisableLogsOpt) {
disableLogsCanonicallyNamedFunctions.push(resolvedFunctionName);
}
hasOneOrMoreCanonicallyNamedFunctions = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put it in else clause (e.g. if all functions named canonically we should just stay at not creating "Allow" policies

@as19ish
Copy link
Contributor Author

as19ish commented Nov 30, 2020

@medikoo ^

@as19ish as19ish requested a review from medikoo November 30, 2020 18:07
Copy link
Contributor

@medikoo medikoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @as19ish !

@medikoo medikoo merged commit ee18167 into serverless:master Dec 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Still, DisableLogs Does Not Disable the Creation of Log Groups
3 participants